-
Notifications
You must be signed in to change notification settings - Fork 75
Expand file tree
/
Copy pathTimedPowerSyncDatabase.ts
More file actions
105 lines (85 loc) · 3.52 KB
/
Copy pathTimedPowerSyncDatabase.ts
File metadata and controls
105 lines (85 loc) · 3.52 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
103
104
105
import {
PowerSyncDatabase,
PowerSyncDBListener,
Transaction,
WebPowerSyncDatabaseOptions,
PowerSyncBackendConnector,
LockContext
} from '@powersync/web';
export enum OperationType {
EXECUTE = 'execute',
READ = 'read',
WRITE = 'write',
READ_TX = 'read-transaction',
WRITE_TX = 'write-transaction'
}
export interface TimedOperation {
type: OperationType;
elapsedTime: number;
}
export interface TimedPowerSyncListener extends PowerSyncDBListener {
operationCompleted: (event: TimedOperation) => void;
}
export class TimedPowerSyncDatabase extends PowerSyncDatabase {
localKey: string;
constructor(options: WebPowerSyncDatabaseOptions) {
super(options);
this.localKey = `${this.database.name}_connecting`;
}
registerListener(listener: Partial<TimedPowerSyncListener>) {
return super.registerListener(listener);
}
async timedExecute(sql: string, parameters?: any[]) {
return this.timed(() => super.execute(sql, parameters));
}
async execute(sql: string, parameters?: any[]) {
return this.timedOperation(OperationType.EXECUTE, () => super.execute(sql, parameters));
}
async getAll<T>(sql: string, parameters?: any[]): Promise<T[]> {
return this.timedOperation(OperationType.READ, () => super.getAll<T>(sql, parameters));
}
async getOptional<T>(sql: string, parameters?: any[]): Promise<T | null> {
return this.timedOperation(OperationType.READ, () => super.getOptional<T>(sql, parameters));
}
async get<T>(sql: string, parameters?: any[]): Promise<T> {
return this.timedOperation(OperationType.READ, () => super.get<T>(sql, parameters));
}
async readTransaction<T>(callback: (tx: Transaction) => Promise<T>, lockTimeout?: number): Promise<T> {
return this.timedOperation(OperationType.READ_TX, () => super.readTransaction<T>(callback, lockTimeout));
}
async timedWriteTransaction<T>(callback: (tx: Transaction) => Promise<T>, lockTimeout?: number) {
return this.timed(() => super.writeTransaction(callback, lockTimeout));
}
async writeTransaction<T>(callback: (tx: Transaction) => Promise<T>, lockTimeout?: number): Promise<T> {
return this.timedOperation(OperationType.WRITE_TX, () => super.writeTransaction<T>(callback, lockTimeout));
}
async readLock<T>(callback: (db: LockContext) => Promise<T>) {
return this.timedOperation(OperationType.READ, () => super.readLock<T>(callback));
}
async writeLock<T>(callback: (db: LockContext) => Promise<T>) {
return this.timedOperation(OperationType.WRITE, () => super.writeLock<T>(callback));
}
async timedOperation<T>(type: OperationType, operation: () => Promise<T>) {
const { elapsedTime, result } = await this.timed<T>(operation);
this.fireOperationComplete({ type, elapsedTime });
return result;
}
async timed<T>(operation: () => Promise<T>) {
const start = Date.now();
const result = await operation();
const elapsedTime = Date.now() - start;
return { elapsedTime, result };
}
async connect(connector: PowerSyncBackendConnector) {
// We toggle this localStorage key to indicate that we are currently connecting
// This will fire a `onStorage` event in other tabs, triggering a reconnect if needed
// We don't need the same for disconnect, as it is triggered with an Abort Signal
localStorage.setItem(this.localKey, 'true');
return super.connect(connector).finally(() => {
localStorage.removeItem(this.localKey);
});
}
fireOperationComplete(event: TimedOperation) {
this.iterateListeners((l) => l.operationCompleted?.(event));
}
}