mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-20 12:11:28 -07:00
fix(anki): avoid unnecessary known-word cache restarts
This commit is contained in:
@@ -110,3 +110,44 @@ test('AnkiIntegrationRuntime switches transports and clears known words when run
|
|||||||
'proxy:start:127.0.0.1:8766:http://127.0.0.1:8765',
|
'proxy:start:127.0.0.1:8766:http://127.0.0.1:8765',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('AnkiIntegrationRuntime skips known-word lifecycle restart for unrelated runtime patches', () => {
|
||||||
|
const { runtime, calls } = createRuntime({
|
||||||
|
knownWords: {
|
||||||
|
highlightEnabled: true,
|
||||||
|
},
|
||||||
|
pollingRate: 250,
|
||||||
|
});
|
||||||
|
|
||||||
|
runtime.start();
|
||||||
|
calls.length = 0;
|
||||||
|
|
||||||
|
runtime.applyRuntimeConfigPatch({
|
||||||
|
behavior: {
|
||||||
|
autoUpdateNewCards: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(calls, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('AnkiIntegrationRuntime restarts known-word lifecycle when known-word settings change', () => {
|
||||||
|
const { runtime, calls } = createRuntime({
|
||||||
|
knownWords: {
|
||||||
|
highlightEnabled: true,
|
||||||
|
refreshMinutes: 90,
|
||||||
|
},
|
||||||
|
pollingRate: 250,
|
||||||
|
});
|
||||||
|
|
||||||
|
runtime.start();
|
||||||
|
calls.length = 0;
|
||||||
|
|
||||||
|
runtime.applyRuntimeConfigPatch({
|
||||||
|
knownWords: {
|
||||||
|
refreshMinutes: 120,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(calls, ['known:start']);
|
||||||
|
});
|
||||||
|
|||||||
@@ -145,6 +145,9 @@ export class AnkiIntegrationRuntime {
|
|||||||
|
|
||||||
applyRuntimeConfigPatch(patch: Partial<AnkiConnectConfig>): void {
|
applyRuntimeConfigPatch(patch: Partial<AnkiConnectConfig>): void {
|
||||||
const wasKnownWordCacheEnabled = this.config.knownWords?.highlightEnabled === true;
|
const wasKnownWordCacheEnabled = this.config.knownWords?.highlightEnabled === true;
|
||||||
|
const previousKnownWordCacheConfig = wasKnownWordCacheEnabled
|
||||||
|
? this.getKnownWordCacheLifecycleConfig(this.config)
|
||||||
|
: null;
|
||||||
const previousTransportKey = this.getTransportConfigKey(this.config);
|
const previousTransportKey = this.getTransportConfigKey(this.config);
|
||||||
|
|
||||||
const mergedConfig: AnkiConnectConfig = {
|
const mergedConfig: AnkiConnectConfig = {
|
||||||
@@ -191,11 +194,19 @@ export class AnkiIntegrationRuntime {
|
|||||||
};
|
};
|
||||||
this.config = normalizeAnkiIntegrationConfig(mergedConfig);
|
this.config = normalizeAnkiIntegrationConfig(mergedConfig);
|
||||||
this.deps.onConfigChanged?.(this.config);
|
this.deps.onConfigChanged?.(this.config);
|
||||||
|
const nextKnownWordCacheEnabled = this.config.knownWords?.highlightEnabled === true;
|
||||||
|
|
||||||
if (wasKnownWordCacheEnabled && this.config.knownWords?.highlightEnabled === false) {
|
if (wasKnownWordCacheEnabled && this.config.knownWords?.highlightEnabled === false) {
|
||||||
this.deps.knownWordCache.stopLifecycle();
|
this.deps.knownWordCache.stopLifecycle();
|
||||||
this.deps.knownWordCache.clearKnownWordCacheState();
|
this.deps.knownWordCache.clearKnownWordCacheState();
|
||||||
} else {
|
} else if (!wasKnownWordCacheEnabled && nextKnownWordCacheEnabled) {
|
||||||
|
this.deps.knownWordCache.startLifecycle();
|
||||||
|
} else if (
|
||||||
|
wasKnownWordCacheEnabled &&
|
||||||
|
nextKnownWordCacheEnabled &&
|
||||||
|
previousKnownWordCacheConfig !== null &&
|
||||||
|
previousKnownWordCacheConfig !== this.getKnownWordCacheLifecycleConfig(this.config)
|
||||||
|
) {
|
||||||
this.deps.knownWordCache.startLifecycle();
|
this.deps.knownWordCache.startLifecycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +217,48 @@ export class AnkiIntegrationRuntime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getKnownWordCacheLifecycleConfig(config: AnkiConnectConfig): string {
|
||||||
|
return JSON.stringify({
|
||||||
|
refreshMinutes: this.getKnownWordRefreshIntervalMinutes(config),
|
||||||
|
scope: this.getKnownWordCacheScopeForConfig(config),
|
||||||
|
fieldsWord: trimToNonEmptyString(config.fields?.word) ?? '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private getKnownWordRefreshIntervalMinutes(config: AnkiConnectConfig): number {
|
||||||
|
const refreshMinutes = config.knownWords?.refreshMinutes;
|
||||||
|
return typeof refreshMinutes === 'number' && Number.isFinite(refreshMinutes) && refreshMinutes > 0
|
||||||
|
? refreshMinutes
|
||||||
|
: DEFAULT_ANKI_CONNECT_CONFIG.knownWords.refreshMinutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getKnownWordCacheScopeForConfig(config: AnkiConnectConfig): string {
|
||||||
|
const configuredDecks = config.knownWords?.decks;
|
||||||
|
if (configuredDecks && typeof configuredDecks === 'object' && !Array.isArray(configuredDecks)) {
|
||||||
|
const normalizedDecks = Object.entries(configuredDecks)
|
||||||
|
.map(([deckName, fields]) => {
|
||||||
|
const name = trimToNonEmptyString(deckName);
|
||||||
|
if (!name) return null;
|
||||||
|
const normalizedFields = Array.isArray(fields)
|
||||||
|
? [
|
||||||
|
...new Set(
|
||||||
|
fields.map(String).map(trimToNonEmptyString).filter((field): field is string => Boolean(field)),
|
||||||
|
),
|
||||||
|
].sort()
|
||||||
|
: [];
|
||||||
|
return [name, normalizedFields];
|
||||||
|
})
|
||||||
|
.filter((entry): entry is [string, string[]] => entry !== null)
|
||||||
|
.sort(([a], [b]) => a.localeCompare(b));
|
||||||
|
if (normalizedDecks.length > 0) {
|
||||||
|
return `decks:${JSON.stringify(normalizedDecks)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const configuredDeck = trimToNonEmptyString(config.deck);
|
||||||
|
return configuredDeck ? `deck:${configuredDeck}` : 'is:note';
|
||||||
|
}
|
||||||
|
|
||||||
getOrCreateProxyServer(): AnkiIntegrationRuntimeProxyServer {
|
getOrCreateProxyServer(): AnkiIntegrationRuntimeProxyServer {
|
||||||
if (!this.proxyServer) {
|
if (!this.proxyServer) {
|
||||||
this.proxyServer = this.deps.proxyServerFactory();
|
this.proxyServer = this.deps.proxyServerFactory();
|
||||||
|
|||||||
Reference in New Issue
Block a user