-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathactivity.ts
More file actions
102 lines (87 loc) · 2.1 KB
/
activity.ts
File metadata and controls
102 lines (87 loc) · 2.1 KB
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Types
export interface ActivityEntry {
id: string;
type: "api" | "fetch";
startTime: number;
endTime?: number;
// For API calls
query?: string;
// For URL fetches
url?: string;
// Result - status is number (HTTP code) or null (pending/network error)
status: number | null;
error?: string;
}
export interface RateLimitInfo {
used: number;
max: number;
oldestTimestamp: number | null;
windowMs: number;
}
export class ActivityMonitor {
private entries: ActivityEntry[] = [];
private readonly maxEntries = 10;
private listeners = new Set<() => void>();
private rateLimitInfo: RateLimitInfo = { used: 0, max: 10, oldestTimestamp: null, windowMs: 60000 };
private nextId = 1;
logStart(partial: Omit<ActivityEntry, "id" | "startTime" | "status">): string {
const id = `act-${this.nextId++}`;
const entry: ActivityEntry = {
...partial,
id,
startTime: Date.now(),
status: null,
};
this.entries.push(entry);
if (this.entries.length > this.maxEntries) {
this.entries.shift();
}
this.notify();
return id;
}
logComplete(id: string, status: number): void {
const entry = this.entries.find((e) => e.id === id);
if (entry) {
entry.endTime = Date.now();
entry.status = status;
this.notify();
}
}
logError(id: string, error: string): void {
const entry = this.entries.find((e) => e.id === id);
if (entry) {
entry.endTime = Date.now();
entry.error = error;
this.notify();
}
}
getEntries(): readonly ActivityEntry[] {
return this.entries;
}
getRateLimitInfo(): RateLimitInfo {
return this.rateLimitInfo;
}
updateRateLimit(info: RateLimitInfo): void {
this.rateLimitInfo = info;
this.notify();
}
onUpdate(callback: () => void): () => void {
this.listeners.add(callback);
return () => this.listeners.delete(callback);
}
clear(): void {
this.entries = [];
this.rateLimitInfo = { used: 0, max: 10, oldestTimestamp: null, windowMs: 60000 };
this.notify();
}
private notify(): void {
for (const cb of this.listeners) {
try {
cb();
} catch {
/* ignore */
}
}
}
}
export const activityMonitor = new ActivityMonitor();