Skip to content

Commit 0a663a2

Browse files
I1712 migration script to add created at updated at in task doc (#1715)
* feat: add function to add createdAt and updatedAt fields * feat: use migration function * test: add test for migration script createdAt and updatedAt * test: fix task count * refactor: update task title * refactor: fix typo * refactor: move task totalTasks * fix: fix test
1 parent 26672d9 commit 0a663a2

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

controllers/tasks.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const { getPaginatedLink } = require("../utils/helper");
1212
const { updateUserStatusOnTaskUpdate, updateStatusOnTaskCompletion } = require("../models/userStatus");
1313
const dataAccess = require("../services/dataAccessLayer");
1414
const { parseSearchQuery } = require("../utils/tasks");
15+
const { addTaskCreatedAtAndUpdatedAtFields } = require("../services/tasks");
1516
/**
1617
* Creates new task
1718
*
@@ -432,6 +433,11 @@ const assignTask = async (req, res) => {
432433

433434
const updateStatus = async (req, res) => {
434435
try {
436+
const { action, field } = req.body;
437+
if (action === "ADD" && field === "CREATED_AT+UPDATED_AT") {
438+
const updateStats = await addTaskCreatedAtAndUpdatedAtFields();
439+
return res.json(updateStats);
440+
}
435441
const response = await tasks.updateTaskStatus();
436442
return res.status(200).json(response);
437443
} catch (error) {

services/tasks.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
const firestore = require("../utils/firestore");
22
const tasksModel = firestore.collection("tasks");
3+
const { chunks } = require("../utils/array");
4+
const { DOCUMENT_WRITE_SIZE: FIRESTORE_BATCH_OPERATIONS_LIMIT } = require("../constants/constants");
5+
36
const updateTaskStatusToDone = async (tasksData) => {
47
const batch = firestore.batch();
58
const tasksBatch = [];
@@ -26,6 +29,51 @@ const updateTaskStatusToDone = async (tasksData) => {
2629
return { ...summary };
2730
}
2831
};
32+
33+
const addTaskCreatedAtAndUpdatedAtFields = async () => {
34+
const operationStats = {
35+
failedTasksIds: [],
36+
totalFailedTasks: 0,
37+
totalTasks: 0,
38+
};
39+
const updatedTasks = [];
40+
const tasks = await tasksModel.get();
41+
42+
if (tasks.empty) {
43+
return operationStats;
44+
}
45+
46+
operationStats.totalTasks = tasks.size;
47+
48+
tasks.forEach(async (task) => {
49+
const taskData = task.data();
50+
taskData.createdAt = task.createTime.seconds;
51+
taskData.updatedAt = task.updateTime.seconds;
52+
updatedTasks.push({ id: task.id, data: taskData });
53+
});
54+
55+
const multipleTasksUpdateBatch = [];
56+
const chunkedTasks = chunks(updatedTasks, FIRESTORE_BATCH_OPERATIONS_LIMIT);
57+
58+
chunkedTasks.forEach(async (tasks) => {
59+
const batch = firestore.batch();
60+
tasks.forEach(({ id, data }) => {
61+
batch.update(tasksModel.doc(id), data);
62+
});
63+
try {
64+
await batch.commit();
65+
multipleTasksUpdateBatch.push(batch);
66+
} catch (error) {
67+
operationStats.totalFailedTasks += tasks.length;
68+
tasks.forEach(({ id }) => operationStats.failedTasksIds.push(id));
69+
}
70+
});
71+
72+
await Promise.allSettled(multipleTasksUpdateBatch);
73+
return operationStats;
74+
};
75+
2976
module.exports = {
3077
updateTaskStatusToDone,
78+
addTaskCreatedAtAndUpdatedAtFields,
3179
};

test/integration/tasks.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,5 +1138,35 @@ describe("Tasks", function () {
11381138
const res = await chai.request(app).post("/tasks/migration").set("cookie", `${cookieName}=${nonSuperUserJwt}`);
11391139
expect(res).to.have.status(401);
11401140
});
1141+
1142+
// TASK createdAt and updatedAt migration script
1143+
it("Should update status createdAt and updatedAt", async function () {
1144+
const res = await chai.request(app).post("/tasks/migration").set("cookie", `${cookieName}=${superUserJwt}`).send({
1145+
action: "ADD",
1146+
field: "CREATED_AT+UPDATED_AT",
1147+
});
1148+
expect(res).to.have.status(200);
1149+
expect(res.body.totalFailedTasks).to.be.equal(0);
1150+
expect(res.body.totalTasks).to.be.equal(23);
1151+
expect(res.body.failedTasksIds).to.deep.equal([]);
1152+
});
1153+
1154+
it("should return failed stats if firestore batch operations fail for adding createdAt and updatedAt", async function () {
1155+
const stub = sinon.stub(firestore, "batch");
1156+
stub.returns({
1157+
update: function () {},
1158+
commit: function () {
1159+
throw new Error("Firestore batch commit failed!");
1160+
},
1161+
});
1162+
const res = await chai.request(app).post("/tasks/migration").set("cookie", `${cookieName}=${superUserJwt}`).send({
1163+
action: "ADD",
1164+
field: "CREATED_AT+UPDATED_AT",
1165+
});
1166+
expect(res).to.have.status(200);
1167+
expect(res.body.totalFailedTasks).to.be.equal(23);
1168+
expect(res.body.totalTasks).to.be.equal(23);
1169+
expect(res.body.failedTasksIds.length).to.equal(23);
1170+
});
11411171
});
11421172
});

0 commit comments

Comments
 (0)