mirror of
https://github.com/urosran/cally.git
synced 2025-07-16 01:56:16 +00:00
Batch updates
This commit is contained in:
@ -293,47 +293,152 @@ exports.sendNotificationOnEventCreation = functions.firestore
|
||||
}
|
||||
});
|
||||
|
||||
// Store batches in Firestore instead of memory
|
||||
async function addToUpdateBatch(eventData, eventId) {
|
||||
const batchId = `${eventData.familyId}_${eventData.lastModifiedBy}`;
|
||||
const batchRef = admin.firestore().collection('UpdateBatches').doc(batchId);
|
||||
|
||||
try {
|
||||
await admin.firestore().runTransaction(async (transaction) => {
|
||||
const batchDoc = await transaction.get(batchRef);
|
||||
|
||||
if (!batchDoc.exists) {
|
||||
// Create new batch
|
||||
transaction.set(batchRef, {
|
||||
familyId: eventData.familyId,
|
||||
lastModifiedBy: eventData.lastModifiedBy,
|
||||
externalOrigin: eventData.externalOrigin,
|
||||
events: [{
|
||||
id: eventId,
|
||||
title: eventData.title,
|
||||
startDate: eventData.startDate
|
||||
}],
|
||||
createdAt: admin.firestore.FieldValue.serverTimestamp(),
|
||||
processed: false
|
||||
});
|
||||
} else {
|
||||
// Update existing batch
|
||||
const existingEvents = batchDoc.data().events || [];
|
||||
transaction.update(batchRef, {
|
||||
events: [...existingEvents, {
|
||||
id: eventId,
|
||||
title: eventData.title,
|
||||
startDate: eventData.startDate
|
||||
}]
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error adding to update batch:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
exports.onEventUpdate = functions.firestore
|
||||
.document('Events/{eventId}')
|
||||
.onUpdate(async (change, context) => {
|
||||
const beforeData = change.before.data();
|
||||
const afterData = change.after.data();
|
||||
const {familyId, title, lastModifiedBy} = afterData;
|
||||
const {familyId, title, lastModifiedBy, externalOrigin, startDate} = afterData;
|
||||
|
||||
// Skip if no meaningful changes
|
||||
if (JSON.stringify(beforeData) === JSON.stringify(afterData)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Get push tokens excluding the user who made the change
|
||||
const pushTokens = await getPushTokensForFamily(familyId, lastModifiedBy);
|
||||
|
||||
const message = `Event "${title}" has been updated`;
|
||||
await sendNotifications(pushTokens, {
|
||||
title: "Event Updated",
|
||||
body: message,
|
||||
data: {
|
||||
type: 'event_update',
|
||||
eventId: context.params.eventId
|
||||
}
|
||||
});
|
||||
|
||||
// Store notification in Firestore
|
||||
await storeNotification({
|
||||
type: 'event_update',
|
||||
await addToUpdateBatch({
|
||||
familyId,
|
||||
content: message,
|
||||
eventId: context.params.eventId,
|
||||
excludedUser: lastModifiedBy,
|
||||
timestamp: admin.firestore.FieldValue.serverTimestamp(),
|
||||
date: eventData.startDate
|
||||
});
|
||||
title,
|
||||
lastModifiedBy,
|
||||
externalOrigin,
|
||||
startDate
|
||||
}, context.params.eventId);
|
||||
} catch (error) {
|
||||
console.error('Error sending event update notification:', error);
|
||||
console.error('Error in onEventUpdate:', error);
|
||||
}
|
||||
});
|
||||
|
||||
// Separate function to process batches
|
||||
exports.processUpdateBatches = functions.pubsub
|
||||
.schedule('every 1 minutes')
|
||||
.onRun(async (context) => {
|
||||
const batchesRef = admin.firestore().collection('UpdateBatches');
|
||||
|
||||
// Find unprocessed batches older than 5 seconds
|
||||
const cutoff = new Date(Date.now() - 5000);
|
||||
const snapshot = await batchesRef
|
||||
.where('processed', '==', false)
|
||||
.where('createdAt', '<=', cutoff)
|
||||
.get();
|
||||
|
||||
const processPromises = snapshot.docs.map(async (doc) => {
|
||||
const batchData = doc.data();
|
||||
|
||||
try {
|
||||
const pushTokens = await getPushTokensForFamily(
|
||||
batchData.familyId,
|
||||
batchData.lastModifiedBy
|
||||
);
|
||||
|
||||
if (pushTokens.length) {
|
||||
let message;
|
||||
if (batchData.externalOrigin) {
|
||||
message = `Calendar sync completed: ${batchData.events.length} events have been updated`;
|
||||
} else {
|
||||
message = batchData.events.length === 1
|
||||
? `Event "${batchData.events[0].title}" has been updated`
|
||||
: `${batchData.events.length} events have been updated`;
|
||||
}
|
||||
|
||||
await sendNotifications(pushTokens, {
|
||||
title: batchData.externalOrigin ? "Calendar Sync Complete" : "Events Updated",
|
||||
body: message,
|
||||
data: {
|
||||
type: 'event_update',
|
||||
count: batchData.events.length
|
||||
}
|
||||
});
|
||||
|
||||
await storeNotification({
|
||||
type: 'event_update',
|
||||
familyId: batchData.familyId,
|
||||
content: message,
|
||||
excludedUser: batchData.lastModifiedBy,
|
||||
timestamp: admin.firestore.FieldValue.serverTimestamp(),
|
||||
count: batchData.events.length,
|
||||
date: batchData.events[0].startDate
|
||||
});
|
||||
}
|
||||
|
||||
// Mark batch as processed
|
||||
await doc.ref.update({
|
||||
processed: true,
|
||||
processedAt: admin.firestore.FieldValue.serverTimestamp()
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error processing batch ${doc.id}:`, error);
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(processPromises);
|
||||
});
|
||||
|
||||
// Cleanup old batches
|
||||
exports.cleanupUpdateBatches = functions.pubsub
|
||||
.schedule('every 24 hours')
|
||||
.onRun(async (context) => {
|
||||
const batchesRef = admin.firestore().collection('UpdateBatches');
|
||||
const dayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
|
||||
const oldBatches = await batchesRef
|
||||
.where('processedAt', '<=', dayAgo)
|
||||
.get();
|
||||
|
||||
const deletePromises = oldBatches.docs.map(doc => doc.ref.delete());
|
||||
await Promise.all(deletePromises);
|
||||
});
|
||||
|
||||
// Upcoming Event Reminders
|
||||
exports.checkUpcomingEvents = functions.pubsub
|
||||
.schedule('every 5 minutes')
|
||||
|
Reference in New Issue
Block a user