Skip to content

Commit 07c17e7

Browse files
Add task change detection to optimize database updates and log update statistics
1 parent 0cb684b commit 07c17e7

File tree

1 file changed

+65
-2
lines changed

1 file changed

+65
-2
lines changed

src/services/task-follower/task-service.ts

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,59 @@ export class TaskService {
130130
}
131131
}
132132

133+
/**
134+
* Check if task has meaningful changes that require database update
135+
* Compares key fields and ignores timestamp-only changes
136+
*/
137+
private hasTaskChanges(existingTask: Task, newTask: Partial<Task>): boolean {
138+
// Fields to compare for changes
139+
const fieldsToCompare: (keyof Task)[] = [
140+
'ownerID', 'ownerName', 'ownerEmail', 'ownerPhone',
141+
'owner_telegram_id', 'owner_telegram_username',
142+
'managerID', 'managerName',
143+
'manager_telegram_id', 'manager_telegram_username',
144+
'points', 'status', 'taskText', 'priority', 'notes', 'milestone'
145+
];
146+
147+
// Check if any field has changed
148+
for (const field of fieldsToCompare) {
149+
const existingValue = existingTask[field];
150+
const newValue = newTask[field];
151+
152+
// Skip if new value is undefined (not being updated)
153+
if (newValue === undefined) continue;
154+
155+
// Compare values (handle null/empty string as equivalent)
156+
const normalizedExisting = existingValue === null ? '' : String(existingValue || '');
157+
const normalizedNew = newValue === null ? '' : String(newValue || '');
158+
159+
if (normalizedExisting !== normalizedNew) {
160+
return true; // Found a difference
161+
}
162+
}
163+
164+
// Check date fields separately
165+
const dateFieldsToCompare: (keyof Task)[] = ['dueDate', 'completed_at', 'blocked_at', 'last_sent', 'last_reported'];
166+
167+
for (const field of dateFieldsToCompare) {
168+
const existingValue = existingTask[field];
169+
const newValue = newTask[field];
170+
171+
// Skip if new value is undefined (not being updated)
172+
if (newValue === undefined) continue;
173+
174+
// Compare dates
175+
const existingDate = existingValue ? new Date(existingValue).getTime() : null;
176+
const newDate = newValue ? new Date(newValue as Date).getTime() : null;
177+
178+
if (existingDate !== newDate) {
179+
return true; // Found a difference
180+
}
181+
}
182+
183+
return false; // No meaningful changes found
184+
}
185+
133186
async updateTaskById(taskId: string, task: Partial<Task>): Promise<Task | null> {
134187
// Populate telegram IDs before updating
135188
await this.populateTelegramIds(task);
@@ -395,6 +448,8 @@ export class TaskService {
395448
}
396449

397450
let rowNumber = 1;
451+
let updatedCount = 0;
452+
let skippedCount = 0;
398453
const pageUserIdsAndNames: Array<[string, string]> = [];
399454

400455
// Get manager from first row or use default
@@ -548,8 +603,13 @@ export class TaskService {
548603
taskObj.last_reported = existingTask.last_reported;
549604
}
550605

551-
// Update existing task
552-
await this.updateTaskById(existingTask.id!, taskObj);
606+
// Only update if there are actual changes (saves database write operations)
607+
if (this.hasTaskChanges(existingTask, taskObj)) {
608+
await this.updateTaskById(existingTask.id!, taskObj);
609+
updatedCount++;
610+
} else {
611+
skippedCount++;
612+
}
553613
} else {
554614
// Create new task
555615
if (send) {
@@ -566,6 +626,9 @@ export class TaskService {
566626
rowNumber++;
567627
}
568628

629+
// Log update statistics for this project
630+
console.log(`Project ${projectName}: ${updatedCount} tasks updated, ${skippedCount} tasks unchanged (${skippedCount > 0 ? Math.round(skippedCount / (updatedCount + skippedCount) * 100) : 0}% saved)`);
631+
569632
// TODO: Handle activity reporting
570633
// const activity = await this.activityCrud.getOrCreateActivity(manager.number, manager.name1, projectName);
571634
// if (activity && shouldSendActivityReport(activity)) {

0 commit comments

Comments
 (0)