fix: complete marketplace client remediation

This commit is contained in:
2026-08-28 23:14:41 +08:00
parent 2c3baf6dff
commit 11d0af0166
18 changed files with 1007 additions and 90 deletions

View File

@@ -92,14 +92,15 @@ export class AccountPluginCache {
library: MarketplaceLibrarySnapshot | null;
resolves: Map<string, MarketplaceResolveSnapshot>;
}>();
private readonly libraryIntents = new Map<string, number>();
getLibrary(binding: AccountBinding): MarketplaceLibrarySnapshot | null {
const record = this.records.get(bindingId(binding));
return record?.library ? clone(record.library) : null;
private nextLibraryIntent(key: string): number {
const next = (this.libraryIntents.get(key) ?? 0) + 1;
this.libraryIntents.set(key, next);
return next;
}
setLibrary(binding: AccountBinding, snapshot: MarketplaceLibrarySnapshot): void {
const key = bindingId(binding);
private setLibrarySnapshot(key: string, binding: AccountBinding, snapshot: MarketplaceLibrarySnapshot): void {
const record = this.records.get(key) ?? {
binding: { accountKey: binding.accountKey, epoch: binding.epoch },
library: null,
@@ -109,8 +110,37 @@ export class AccountPluginCache {
this.records.set(key, record);
}
markLibraryStale(binding: AccountBinding): MarketplaceLibrarySnapshot | null {
getLibrary(binding: AccountBinding): MarketplaceLibrarySnapshot | null {
const record = this.records.get(bindingId(binding));
return record?.library ? clone(record.library) : null;
}
setLibrary(binding: AccountBinding, snapshot: MarketplaceLibrarySnapshot): void {
const key = bindingId(binding);
this.nextLibraryIntent(key);
this.setLibrarySnapshot(key, binding, snapshot);
}
/** Reserve the commit slot before an async Library read or mutation starts. */
beginLibraryIntent(binding: AccountBinding): number {
return this.nextLibraryIntent(bindingId(binding));
}
/** Commit only the latest read/mutation intent for this account binding. */
commitLibrary(
binding: AccountBinding,
intent: number,
snapshot: MarketplaceLibrarySnapshot,
): boolean {
const key = bindingId(binding);
if (this.libraryIntents.get(key) !== intent) return false;
this.setLibrarySnapshot(key, binding, snapshot);
return true;
}
markLibraryStale(binding: AccountBinding, intent?: number): MarketplaceLibrarySnapshot | null {
const key = bindingId(binding);
if (intent !== undefined && this.libraryIntents.get(key) !== intent) return null;
const record = this.records.get(key);
if (!record?.library) return null;
record.library = { ...record.library, stale: true };
@@ -193,12 +223,16 @@ export class AccountPluginCache {
clearAccount(binding: AccountBinding): void {
assertBinding(binding);
for (const [key, record] of this.records.entries()) {
if (record.binding.accountKey === binding.accountKey) this.records.delete(key);
if (record.binding.accountKey === binding.accountKey) {
this.records.delete(key);
this.libraryIntents.delete(key);
}
}
}
invalidateAll(): void {
this.records.clear();
this.libraryIntents.clear();
}
clear(): void {