File size: 1,876 Bytes
a4c3fca
 
 
 
ddbe7d2
a4c3fca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ddbe7d2
 
a4c3fca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { client, collections } from "$lib/server/database";
import { acquireLock, refreshLock } from "$lib/migrations/lock";
import type { ObjectId } from "mongodb";
import { subDays } from "date-fns";
import { logger } from "$lib/server/logger";

const LOCK_KEY = "assistants.count";

let hasLock = false;
let lockId: ObjectId | null = null;

async function refreshAssistantsCountsHelper() {
	if (!hasLock) {
		return;
	}

	try {
		await client.withSession((session) =>
			session.withTransaction(async () => {
				await collections.assistants
					.aggregate([
						{ $project: { _id: 1 } },
						{ $set: { last24HoursCount: 0 } },
						{
							$unionWith: {
								coll: "assistants.stats",
								pipeline: [
									{ $match: { "date.at": { $gte: subDays(new Date(), 1) }, "date.span": "hour" } },
									{
										$group: {
											_id: "$assistantId",
											last24HoursCount: { $sum: "$count" },
										},
									},
								],
							},
						},
						{
							$group: {
								_id: "$_id",
								last24HoursCount: { $sum: "$last24HoursCount" },
							},
						},
						{
							$merge: {
								into: "assistants",
								on: "_id",
								whenMatched: "merge",
								whenNotMatched: "discard",
							},
						},
					])
					.next();
			})
		);
	} catch (e) {
		logger.error("Refresh assistants counter failed!");
		logger.error(e);
	}
}

async function maintainLock() {
	if (hasLock && lockId) {
		hasLock = await refreshLock(LOCK_KEY, lockId);

		if (!hasLock) {
			lockId = null;
		}
	} else if (!hasLock) {
		lockId = (await acquireLock(LOCK_KEY)) || null;
		hasLock = !!lockId;
	}

	setTimeout(maintainLock, 10_000);
}

export function refreshAssistantsCounts() {
	const ONE_HOUR_MS = 3_600_000;

	maintainLock().then(() => {
		refreshAssistantsCountsHelper();

		setInterval(refreshAssistantsCountsHelper, ONE_HOUR_MS);
	});
}