Skip to content

Commit 3bbcc9e

Browse files
authored
fix: pictique replay (#338)
1 parent 55d0e57 commit 3bbcc9e

File tree

7 files changed

+100
-77
lines changed

7 files changed

+100
-77
lines changed
-1.53 KB
Binary file not shown.
-1.44 KB
Binary file not shown.
-15.7 MB
Binary file not shown.
-15.7 MB
Binary file not shown.

infrastructure/eid-wallet/src-tauri/gen/android/app/arm64/release/output-metadata.json

Lines changed: 0 additions & 37 deletions
This file was deleted.

infrastructure/eid-wallet/src/routes/(app)/settings/+page.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@
126126
on:click={handleVersionTap}
127127
disabled={isRetrying}
128128
>
129-
Version v0.2.1.1
129+
Version v0.2.1.2
130130
</button>
131131

132132
{#if retryMessage}

platforms/pictique-api/src/web3adapter/watchers/subscriber.ts

Lines changed: 99 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,30 @@ const JUNCTION_TABLE_MAP = {
3333
@EventSubscriber()
3434
export class PostgresSubscriber implements EntitySubscriberInterface {
3535
private adapter: Web3Adapter;
36+
private pendingChanges: Map<string, number> = new Map();
3637

3738
constructor() {
3839
this.adapter = adapter;
40+
41+
// Clean up old pending changes every 5 minutes to prevent memory leaks
42+
setInterval(() => {
43+
this.cleanupOldPendingChanges();
44+
}, 5 * 60 * 1000);
45+
}
46+
47+
/**
48+
* Clean up old pending changes to prevent memory leaks
49+
*/
50+
private cleanupOldPendingChanges(): void {
51+
const now = Date.now();
52+
const maxAge = 10 * 60 * 1000; // 10 minutes
53+
54+
for (const [key, timestamp] of this.pendingChanges.entries()) {
55+
if (now - timestamp > maxAge) {
56+
this.pendingChanges.delete(key);
57+
console.log(`Cleaned up old pending change: ${key}`);
58+
}
59+
}
3960
}
4061

4162
/**
@@ -164,28 +185,49 @@ export class PostgresSubscriber implements EntitySubscriberInterface {
164185
const data = this.entityToPlain(entity);
165186
if (!data.id) return;
166187

188+
// Create a unique key for this entity change to prevent duplicates
189+
const changeKey = `${tableName}:${entity.id}`;
190+
191+
// Check if we already have a pending change for this entity
192+
if (this.pendingChanges.has(changeKey)) {
193+
console.log(`Change already pending for ${changeKey}, skipping duplicate`);
194+
return;
195+
}
196+
197+
// Mark this change as pending with timestamp
198+
this.pendingChanges.set(changeKey, Date.now());
199+
167200
try {
168201
setTimeout(async () => {
169-
let globalId = await this.adapter.mappingDb.getGlobalId(
170-
entity.id
171-
);
172-
globalId = globalId ?? "";
173-
174-
if (this.adapter.lockedIds.includes(globalId))
175-
return console.log("locked skipping ", globalId);
176-
177-
console.log(
178-
"sending packet for global Id",
179-
globalId,
180-
entity.id
181-
);
182-
const envelope = await this.adapter.handleChange({
183-
data,
184-
tableName: tableName.toLowerCase(),
185-
});
202+
try {
203+
let globalId = await this.adapter.mappingDb.getGlobalId(
204+
entity.id
205+
);
206+
globalId = globalId ?? "";
207+
208+
if (this.adapter.lockedIds.includes(globalId)) {
209+
console.log("locked skipping ", globalId);
210+
return;
211+
}
212+
213+
console.log(
214+
"sending packet for global Id",
215+
globalId,
216+
entity.id
217+
);
218+
const envelope = await this.adapter.handleChange({
219+
data,
220+
tableName: tableName.toLowerCase(),
221+
});
222+
} finally {
223+
// Always remove the pending change flag
224+
this.pendingChanges.delete(changeKey);
225+
}
186226
}, 3_000);
187227
} catch (error) {
188228
console.error(`Error processing change for ${tableName}:`, error);
229+
// Remove the pending change flag on error
230+
this.pendingChanges.delete(changeKey);
189231
}
190232
}
191233

@@ -217,34 +259,52 @@ export class PostgresSubscriber implements EntitySubscriberInterface {
217259
return;
218260
}
219261

220-
let globalId = await this.adapter.mappingDb.getGlobalId(entity.id);
221-
globalId = globalId ?? "";
262+
// Create a unique key for this junction table change to prevent duplicates
263+
const changeKey = `junction:${junctionInfo.entity}:${parentId}`;
264+
265+
// Check if we already have a pending change for this parent entity
266+
if (this.pendingChanges.has(changeKey)) {
267+
console.log(`Junction change already pending for ${changeKey}, skipping duplicate`);
268+
return;
269+
}
270+
271+
// Mark this change as pending with timestamp
272+
this.pendingChanges.set(changeKey, Date.now());
222273

223-
// Use immediate locking instead of setTimeout to prevent race conditions
274+
// Use setTimeout to prevent race conditions
224275
try {
225276
setTimeout(async () => {
226-
let globalId = await this.adapter.mappingDb.getGlobalId(
227-
entity.id
228-
);
229-
globalId = globalId ?? "";
230-
231-
if (this.adapter.lockedIds.includes(globalId))
232-
return console.log("locked skipping ", globalId);
233-
234-
console.log(
235-
"sending packet for global Id",
236-
globalId,
237-
entity.id
238-
);
239-
240-
const tableName = `${junctionInfo.entity.toLowerCase()}s`;
241-
await this.adapter.handleChange({
242-
data: this.entityToPlain(parentEntity),
243-
tableName,
244-
});
277+
try {
278+
let globalId = await this.adapter.mappingDb.getGlobalId(
279+
entity.id
280+
);
281+
globalId = globalId ?? "";
282+
283+
if (this.adapter.lockedIds.includes(globalId)) {
284+
console.log("locked skipping ", globalId);
285+
return;
286+
}
287+
288+
console.log(
289+
"sending packet for global Id",
290+
globalId,
291+
entity.id
292+
);
293+
294+
const tableName = `${junctionInfo.entity.toLowerCase()}s`;
295+
await this.adapter.handleChange({
296+
data: this.entityToPlain(parentEntity),
297+
tableName,
298+
});
299+
} finally {
300+
// Always remove the pending change flag
301+
this.pendingChanges.delete(changeKey);
302+
}
245303
}, 3_000);
246304
} catch (error) {
247305
console.error(error);
306+
// Remove the pending change flag on error
307+
this.pendingChanges.delete(changeKey);
248308
}
249309
} catch (error) {
250310
console.error("Error handling junction table change:", error);

0 commit comments

Comments
 (0)