mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-21 23:11:01 +00:00
fix: defer plugin runtime globals until use
This commit is contained in:
@@ -51,16 +51,18 @@ type FeishuThreadBindingsState = {
|
||||
};
|
||||
|
||||
const FEISHU_THREAD_BINDINGS_STATE_KEY = Symbol.for("openclaw.feishuThreadBindingsState");
|
||||
const state = resolveGlobalSingleton<FeishuThreadBindingsState>(
|
||||
FEISHU_THREAD_BINDINGS_STATE_KEY,
|
||||
() => ({
|
||||
managersByAccountId: new Map(),
|
||||
bindingsByAccountConversation: new Map(),
|
||||
}),
|
||||
);
|
||||
let state: FeishuThreadBindingsState | undefined;
|
||||
|
||||
const MANAGERS_BY_ACCOUNT_ID = state.managersByAccountId;
|
||||
const BINDINGS_BY_ACCOUNT_CONVERSATION = state.bindingsByAccountConversation;
|
||||
function getState(): FeishuThreadBindingsState {
|
||||
state ??= resolveGlobalSingleton<FeishuThreadBindingsState>(
|
||||
FEISHU_THREAD_BINDINGS_STATE_KEY,
|
||||
() => ({
|
||||
managersByAccountId: new Map(),
|
||||
bindingsByAccountConversation: new Map(),
|
||||
}),
|
||||
);
|
||||
return state;
|
||||
}
|
||||
|
||||
function resolveBindingKey(params: { accountId: string; conversationId: string }): string {
|
||||
return `${params.accountId}:${params.conversationId}`;
|
||||
@@ -119,7 +121,7 @@ export function createFeishuThreadBindingManager(params: {
|
||||
cfg: OpenClawConfig;
|
||||
}): FeishuThreadBindingManager {
|
||||
const accountId = normalizeAccountId(params.accountId);
|
||||
const existing = MANAGERS_BY_ACCOUNT_ID.get(accountId);
|
||||
const existing = getState().managersByAccountId.get(accountId);
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
@@ -138,9 +140,11 @@ export function createFeishuThreadBindingManager(params: {
|
||||
const manager: FeishuThreadBindingManager = {
|
||||
accountId,
|
||||
getByConversationId: (conversationId) =>
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.get(resolveBindingKey({ accountId, conversationId })),
|
||||
getState().bindingsByAccountConversation.get(
|
||||
resolveBindingKey({ accountId, conversationId }),
|
||||
),
|
||||
listBySessionKey: (targetSessionKey) =>
|
||||
[...BINDINGS_BY_ACCOUNT_CONVERSATION.values()].filter(
|
||||
[...getState().bindingsByAccountConversation.values()].filter(
|
||||
(record) => record.accountId === accountId && record.targetSessionKey === targetSessionKey,
|
||||
),
|
||||
bindConversation: ({
|
||||
@@ -184,7 +188,7 @@ export function createFeishuThreadBindingManager(params: {
|
||||
boundAt: now,
|
||||
lastActivityAt: now,
|
||||
};
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.set(
|
||||
getState().bindingsByAccountConversation.set(
|
||||
resolveBindingKey({ accountId, conversationId: normalizedConversationId }),
|
||||
record,
|
||||
);
|
||||
@@ -192,30 +196,30 @@ export function createFeishuThreadBindingManager(params: {
|
||||
},
|
||||
touchConversation: (conversationId, at = Date.now()) => {
|
||||
const key = resolveBindingKey({ accountId, conversationId });
|
||||
const existingRecord = BINDINGS_BY_ACCOUNT_CONVERSATION.get(key);
|
||||
const existingRecord = getState().bindingsByAccountConversation.get(key);
|
||||
if (!existingRecord) {
|
||||
return null;
|
||||
}
|
||||
const updated = { ...existingRecord, lastActivityAt: at };
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.set(key, updated);
|
||||
getState().bindingsByAccountConversation.set(key, updated);
|
||||
return updated;
|
||||
},
|
||||
unbindConversation: (conversationId) => {
|
||||
const key = resolveBindingKey({ accountId, conversationId });
|
||||
const existingRecord = BINDINGS_BY_ACCOUNT_CONVERSATION.get(key);
|
||||
const existingRecord = getState().bindingsByAccountConversation.get(key);
|
||||
if (!existingRecord) {
|
||||
return null;
|
||||
}
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.delete(key);
|
||||
getState().bindingsByAccountConversation.delete(key);
|
||||
return existingRecord;
|
||||
},
|
||||
unbindBySessionKey: (targetSessionKey) => {
|
||||
const removed: FeishuThreadBindingRecord[] = [];
|
||||
for (const record of [...BINDINGS_BY_ACCOUNT_CONVERSATION.values()]) {
|
||||
for (const record of [...getState().bindingsByAccountConversation.values()]) {
|
||||
if (record.accountId !== accountId || record.targetSessionKey !== targetSessionKey) {
|
||||
continue;
|
||||
}
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.delete(
|
||||
getState().bindingsByAccountConversation.delete(
|
||||
resolveBindingKey({ accountId, conversationId: record.conversationId }),
|
||||
);
|
||||
removed.push(record);
|
||||
@@ -223,12 +227,12 @@ export function createFeishuThreadBindingManager(params: {
|
||||
return removed;
|
||||
},
|
||||
stop: () => {
|
||||
for (const key of [...BINDINGS_BY_ACCOUNT_CONVERSATION.keys()]) {
|
||||
for (const key of [...getState().bindingsByAccountConversation.keys()]) {
|
||||
if (key.startsWith(`${accountId}:`)) {
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.delete(key);
|
||||
getState().bindingsByAccountConversation.delete(key);
|
||||
}
|
||||
}
|
||||
MANAGERS_BY_ACCOUNT_ID.delete(accountId);
|
||||
getState().managersByAccountId.delete(accountId);
|
||||
unregisterSessionBindingAdapter({ channel: "feishu", accountId });
|
||||
},
|
||||
};
|
||||
@@ -290,22 +294,22 @@ export function createFeishuThreadBindingManager(params: {
|
||||
},
|
||||
});
|
||||
|
||||
MANAGERS_BY_ACCOUNT_ID.set(accountId, manager);
|
||||
getState().managersByAccountId.set(accountId, manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
export function getFeishuThreadBindingManager(
|
||||
accountId?: string,
|
||||
): FeishuThreadBindingManager | null {
|
||||
return MANAGERS_BY_ACCOUNT_ID.get(normalizeAccountId(accountId)) ?? null;
|
||||
return getState().managersByAccountId.get(normalizeAccountId(accountId)) ?? null;
|
||||
}
|
||||
|
||||
export const __testing = {
|
||||
resetFeishuThreadBindingsForTests() {
|
||||
for (const manager of MANAGERS_BY_ACCOUNT_ID.values()) {
|
||||
for (const manager of getState().managersByAccountId.values()) {
|
||||
manager.stop();
|
||||
}
|
||||
MANAGERS_BY_ACCOUNT_ID.clear();
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.clear();
|
||||
getState().managersByAccountId.clear();
|
||||
getState().bindingsByAccountConversation.clear();
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,7 +15,12 @@ const MAX_ENTRIES = 5000;
|
||||
*/
|
||||
const SLACK_THREAD_PARTICIPATION_KEY = Symbol.for("openclaw.slackThreadParticipation");
|
||||
|
||||
const threadParticipation = resolveGlobalMap<string, number>(SLACK_THREAD_PARTICIPATION_KEY);
|
||||
let threadParticipation: Map<string, number> | undefined;
|
||||
|
||||
function getThreadParticipation(): Map<string, number> {
|
||||
threadParticipation ??= resolveGlobalMap<string, number>(SLACK_THREAD_PARTICIPATION_KEY);
|
||||
return threadParticipation;
|
||||
}
|
||||
|
||||
function makeKey(accountId: string, channelId: string, threadTs: string): string {
|
||||
return `${accountId}:${channelId}:${threadTs}`;
|
||||
@@ -23,17 +28,17 @@ function makeKey(accountId: string, channelId: string, threadTs: string): string
|
||||
|
||||
function evictExpired(): void {
|
||||
const now = Date.now();
|
||||
for (const [key, timestamp] of threadParticipation) {
|
||||
for (const [key, timestamp] of getThreadParticipation()) {
|
||||
if (now - timestamp > TTL_MS) {
|
||||
threadParticipation.delete(key);
|
||||
getThreadParticipation().delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function evictOldest(): void {
|
||||
const oldest = threadParticipation.keys().next().value;
|
||||
const oldest = getThreadParticipation().keys().next().value;
|
||||
if (oldest) {
|
||||
threadParticipation.delete(oldest);
|
||||
getThreadParticipation().delete(oldest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +50,7 @@ export function recordSlackThreadParticipation(
|
||||
if (!accountId || !channelId || !threadTs) {
|
||||
return;
|
||||
}
|
||||
const threadParticipation = getThreadParticipation();
|
||||
if (threadParticipation.size >= MAX_ENTRIES) {
|
||||
evictExpired();
|
||||
}
|
||||
@@ -63,6 +69,7 @@ export function hasSlackThreadParticipation(
|
||||
return false;
|
||||
}
|
||||
const key = makeKey(accountId, channelId, threadTs);
|
||||
const threadParticipation = getThreadParticipation();
|
||||
const timestamp = threadParticipation.get(key);
|
||||
if (timestamp == null) {
|
||||
return false;
|
||||
@@ -75,5 +82,5 @@ export function hasSlackThreadParticipation(
|
||||
}
|
||||
|
||||
export function clearSlackThreadParticipationCache(): void {
|
||||
threadParticipation.clear();
|
||||
getThreadParticipation().clear();
|
||||
}
|
||||
|
||||
@@ -28,11 +28,17 @@ type TelegramSendMessageDraft = (
|
||||
*/
|
||||
const TELEGRAM_DRAFT_STREAM_STATE_KEY = Symbol.for("openclaw.telegramDraftStreamState");
|
||||
|
||||
const draftStreamState = resolveGlobalSingleton(TELEGRAM_DRAFT_STREAM_STATE_KEY, () => ({
|
||||
nextDraftId: 0,
|
||||
}));
|
||||
let draftStreamState: { nextDraftId: number } | undefined;
|
||||
|
||||
function getDraftStreamState(): { nextDraftId: number } {
|
||||
draftStreamState ??= resolveGlobalSingleton(TELEGRAM_DRAFT_STREAM_STATE_KEY, () => ({
|
||||
nextDraftId: 0,
|
||||
}));
|
||||
return draftStreamState;
|
||||
}
|
||||
|
||||
function allocateTelegramDraftId(): number {
|
||||
const draftStreamState = getDraftStreamState();
|
||||
draftStreamState.nextDraftId =
|
||||
draftStreamState.nextDraftId >= TELEGRAM_DRAFT_ID_MAX ? 1 : draftStreamState.nextDraftId + 1;
|
||||
return draftStreamState.nextDraftId;
|
||||
@@ -454,6 +460,6 @@ export function createTelegramDraftStream(params: {
|
||||
|
||||
export const __testing = {
|
||||
resetTelegramDraftStreamForTests() {
|
||||
draftStreamState.nextDraftId = 0;
|
||||
getDraftStreamState().nextDraftId = 0;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -103,17 +103,34 @@ function escapeRegex(str: string): string {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
}
|
||||
|
||||
const FILE_EXTENSIONS_PATTERN = Array.from(FILE_REF_EXTENSIONS_WITH_TLD).map(escapeRegex).join("|");
|
||||
const AUTO_LINKED_ANCHOR_PATTERN = /<a\s+href="https?:\/\/([^"]+)"[^>]*>\1<\/a>/gi;
|
||||
const FILE_REFERENCE_PATTERN = new RegExp(
|
||||
`(^|[^a-zA-Z0-9_\\-/])([a-zA-Z0-9_.\\-./]+\\.(?:${FILE_EXTENSIONS_PATTERN}))(?=$|[^a-zA-Z0-9_\\-/])`,
|
||||
"gi",
|
||||
);
|
||||
const ORPHANED_TLD_PATTERN = new RegExp(
|
||||
`([^a-zA-Z0-9]|^)([A-Za-z]\\.(?:${FILE_EXTENSIONS_PATTERN}))(?=[^a-zA-Z0-9/]|$)`,
|
||||
"g",
|
||||
);
|
||||
const HTML_TAG_PATTERN = /(<\/?)([a-zA-Z][a-zA-Z0-9-]*)\b[^>]*?>/gi;
|
||||
let fileReferencePattern: RegExp | undefined;
|
||||
let orphanedTldPattern: RegExp | undefined;
|
||||
|
||||
function getFileReferencePattern(): RegExp {
|
||||
if (fileReferencePattern) {
|
||||
return fileReferencePattern;
|
||||
}
|
||||
const fileExtensionsPattern = Array.from(FILE_REF_EXTENSIONS_WITH_TLD).map(escapeRegex).join("|");
|
||||
fileReferencePattern = new RegExp(
|
||||
`(^|[^a-zA-Z0-9_\\-/])([a-zA-Z0-9_.\\-./]+\\.(?:${fileExtensionsPattern}))(?=$|[^a-zA-Z0-9_\\-/])`,
|
||||
"gi",
|
||||
);
|
||||
return fileReferencePattern;
|
||||
}
|
||||
|
||||
function getOrphanedTldPattern(): RegExp {
|
||||
if (orphanedTldPattern) {
|
||||
return orphanedTldPattern;
|
||||
}
|
||||
const fileExtensionsPattern = Array.from(FILE_REF_EXTENSIONS_WITH_TLD).map(escapeRegex).join("|");
|
||||
orphanedTldPattern = new RegExp(
|
||||
`([^a-zA-Z0-9]|^)([A-Za-z]\\.(?:${fileExtensionsPattern}))(?=[^a-zA-Z0-9/]|$)`,
|
||||
"g",
|
||||
);
|
||||
return orphanedTldPattern;
|
||||
}
|
||||
|
||||
function wrapStandaloneFileRef(match: string, prefix: string, filename: string): string {
|
||||
if (filename.startsWith("//")) {
|
||||
@@ -134,8 +151,8 @@ function wrapSegmentFileRefs(
|
||||
if (!text || codeDepth > 0 || preDepth > 0 || anchorDepth > 0) {
|
||||
return text;
|
||||
}
|
||||
const wrappedStandalone = text.replace(FILE_REFERENCE_PATTERN, wrapStandaloneFileRef);
|
||||
return wrappedStandalone.replace(ORPHANED_TLD_PATTERN, (match, prefix: string, tld: string) =>
|
||||
const wrappedStandalone = text.replace(getFileReferencePattern(), wrapStandaloneFileRef);
|
||||
return wrappedStandalone.replace(getOrphanedTldPattern(), (match, prefix: string, tld: string) =>
|
||||
prefix === ">" ? match : `${prefix}<code>${escapeHtml(tld)}</code>`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,12 @@ type CacheEntry = {
|
||||
*/
|
||||
const TELEGRAM_SENT_MESSAGES_KEY = Symbol.for("openclaw.telegramSentMessages");
|
||||
|
||||
const sentMessages = resolveGlobalMap<string, CacheEntry>(TELEGRAM_SENT_MESSAGES_KEY);
|
||||
let sentMessages: Map<string, CacheEntry> | undefined;
|
||||
|
||||
function getSentMessages(): Map<string, CacheEntry> {
|
||||
sentMessages ??= resolveGlobalMap<string, CacheEntry>(TELEGRAM_SENT_MESSAGES_KEY);
|
||||
return sentMessages;
|
||||
}
|
||||
|
||||
function getChatKey(chatId: number | string): string {
|
||||
return String(chatId);
|
||||
@@ -37,6 +42,7 @@ function cleanupExpired(entry: CacheEntry): void {
|
||||
*/
|
||||
export function recordSentMessage(chatId: number | string, messageId: number): void {
|
||||
const key = getChatKey(chatId);
|
||||
const sentMessages = getSentMessages();
|
||||
let entry = sentMessages.get(key);
|
||||
if (!entry) {
|
||||
entry = { timestamps: new Map() };
|
||||
@@ -54,7 +60,7 @@ export function recordSentMessage(chatId: number | string, messageId: number): v
|
||||
*/
|
||||
export function wasSentByBot(chatId: number | string, messageId: number): boolean {
|
||||
const key = getChatKey(chatId);
|
||||
const entry = sentMessages.get(key);
|
||||
const entry = getSentMessages().get(key);
|
||||
if (!entry) {
|
||||
return false;
|
||||
}
|
||||
@@ -67,5 +73,5 @@ export function wasSentByBot(chatId: number | string, messageId: number): boolea
|
||||
* Clear all cached entries (for testing).
|
||||
*/
|
||||
export function clearSentMessageCache(): void {
|
||||
sentMessages.clear();
|
||||
getSentMessages().clear();
|
||||
}
|
||||
|
||||
@@ -77,17 +77,19 @@ type TelegramThreadBindingsState = {
|
||||
*/
|
||||
const TELEGRAM_THREAD_BINDINGS_STATE_KEY = Symbol.for("openclaw.telegramThreadBindingsState");
|
||||
|
||||
const threadBindingsState = resolveGlobalSingleton<TelegramThreadBindingsState>(
|
||||
TELEGRAM_THREAD_BINDINGS_STATE_KEY,
|
||||
() => ({
|
||||
managersByAccountId: new Map<string, TelegramThreadBindingManager>(),
|
||||
bindingsByAccountConversation: new Map<string, TelegramThreadBindingRecord>(),
|
||||
persistQueueByAccountId: new Map<string, Promise<void>>(),
|
||||
}),
|
||||
);
|
||||
const MANAGERS_BY_ACCOUNT_ID = threadBindingsState.managersByAccountId;
|
||||
const BINDINGS_BY_ACCOUNT_CONVERSATION = threadBindingsState.bindingsByAccountConversation;
|
||||
const PERSIST_QUEUE_BY_ACCOUNT_ID = threadBindingsState.persistQueueByAccountId;
|
||||
let threadBindingsState: TelegramThreadBindingsState | undefined;
|
||||
|
||||
function getThreadBindingsState(): TelegramThreadBindingsState {
|
||||
threadBindingsState ??= resolveGlobalSingleton<TelegramThreadBindingsState>(
|
||||
TELEGRAM_THREAD_BINDINGS_STATE_KEY,
|
||||
() => ({
|
||||
managersByAccountId: new Map<string, TelegramThreadBindingManager>(),
|
||||
bindingsByAccountConversation: new Map<string, TelegramThreadBindingRecord>(),
|
||||
persistQueueByAccountId: new Map<string, Promise<void>>(),
|
||||
}),
|
||||
);
|
||||
return threadBindingsState;
|
||||
}
|
||||
|
||||
function normalizeDurationMs(raw: unknown, fallback: number): number {
|
||||
if (typeof raw !== "number" || !Number.isFinite(raw)) {
|
||||
@@ -168,7 +170,7 @@ function fromSessionBindingInput(params: {
|
||||
}): TelegramThreadBindingRecord {
|
||||
const now = Date.now();
|
||||
const metadata = params.input.metadata ?? {};
|
||||
const existing = BINDINGS_BY_ACCOUNT_CONVERSATION.get(
|
||||
const existing = getThreadBindingsState().bindingsByAccountConversation.get(
|
||||
resolveBindingKey({
|
||||
accountId: params.accountId,
|
||||
conversationId: params.input.conversationId,
|
||||
@@ -310,7 +312,7 @@ async function persistBindingsToDisk(params: {
|
||||
version: STORE_VERSION,
|
||||
bindings:
|
||||
params.bindings ??
|
||||
[...BINDINGS_BY_ACCOUNT_CONVERSATION.values()].filter(
|
||||
[...getThreadBindingsState().bindingsByAccountConversation.values()].filter(
|
||||
(entry) => entry.accountId === params.accountId,
|
||||
),
|
||||
};
|
||||
@@ -322,7 +324,7 @@ async function persistBindingsToDisk(params: {
|
||||
}
|
||||
|
||||
function listBindingsForAccount(accountId: string): TelegramThreadBindingRecord[] {
|
||||
return [...BINDINGS_BY_ACCOUNT_CONVERSATION.values()].filter(
|
||||
return [...getThreadBindingsState().bindingsByAccountConversation.values()].filter(
|
||||
(entry) => entry.accountId === accountId,
|
||||
);
|
||||
}
|
||||
@@ -335,16 +337,17 @@ function enqueuePersistBindings(params: {
|
||||
if (!params.persist) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const previous = PERSIST_QUEUE_BY_ACCOUNT_ID.get(params.accountId) ?? Promise.resolve();
|
||||
const previous =
|
||||
getThreadBindingsState().persistQueueByAccountId.get(params.accountId) ?? Promise.resolve();
|
||||
const next = previous
|
||||
.catch(() => undefined)
|
||||
.then(async () => {
|
||||
await persistBindingsToDisk(params);
|
||||
});
|
||||
PERSIST_QUEUE_BY_ACCOUNT_ID.set(params.accountId, next);
|
||||
getThreadBindingsState().persistQueueByAccountId.set(params.accountId, next);
|
||||
void next.finally(() => {
|
||||
if (PERSIST_QUEUE_BY_ACCOUNT_ID.get(params.accountId) === next) {
|
||||
PERSIST_QUEUE_BY_ACCOUNT_ID.delete(params.accountId);
|
||||
if (getThreadBindingsState().persistQueueByAccountId.get(params.accountId) === next) {
|
||||
getThreadBindingsState().persistQueueByAccountId.delete(params.accountId);
|
||||
}
|
||||
});
|
||||
return next;
|
||||
@@ -412,7 +415,7 @@ export function createTelegramThreadBindingManager(
|
||||
} = {},
|
||||
): TelegramThreadBindingManager {
|
||||
const accountId = normalizeAccountId(params.accountId);
|
||||
const existing = MANAGERS_BY_ACCOUNT_ID.get(accountId);
|
||||
const existing = getThreadBindingsState().managersByAccountId.get(accountId);
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
@@ -430,7 +433,7 @@ export function createTelegramThreadBindingManager(
|
||||
accountId,
|
||||
conversationId: entry.conversationId,
|
||||
});
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.set(key, {
|
||||
getThreadBindingsState().bindingsByAccountConversation.set(key, {
|
||||
...entry,
|
||||
accountId,
|
||||
});
|
||||
@@ -448,7 +451,7 @@ export function createTelegramThreadBindingManager(
|
||||
if (!conversationId) {
|
||||
return undefined;
|
||||
}
|
||||
return BINDINGS_BY_ACCOUNT_CONVERSATION.get(
|
||||
return getThreadBindingsState().bindingsByAccountConversation.get(
|
||||
resolveBindingKey({
|
||||
accountId,
|
||||
conversationId,
|
||||
@@ -471,7 +474,7 @@ export function createTelegramThreadBindingManager(
|
||||
return null;
|
||||
}
|
||||
const key = resolveBindingKey({ accountId, conversationId });
|
||||
const existing = BINDINGS_BY_ACCOUNT_CONVERSATION.get(key);
|
||||
const existing = getThreadBindingsState().bindingsByAccountConversation.get(key);
|
||||
if (!existing) {
|
||||
return null;
|
||||
}
|
||||
@@ -479,7 +482,7 @@ export function createTelegramThreadBindingManager(
|
||||
...existing,
|
||||
lastActivityAt: normalizeTimestampMs(at ?? Date.now()),
|
||||
};
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.set(key, nextRecord);
|
||||
getThreadBindingsState().bindingsByAccountConversation.set(key, nextRecord);
|
||||
persistBindingsSafely({
|
||||
accountId,
|
||||
persist: manager.shouldPersistMutations(),
|
||||
@@ -494,11 +497,11 @@ export function createTelegramThreadBindingManager(
|
||||
return null;
|
||||
}
|
||||
const key = resolveBindingKey({ accountId, conversationId });
|
||||
const removed = BINDINGS_BY_ACCOUNT_CONVERSATION.get(key) ?? null;
|
||||
const removed = getThreadBindingsState().bindingsByAccountConversation.get(key) ?? null;
|
||||
if (!removed) {
|
||||
return null;
|
||||
}
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.delete(key);
|
||||
getThreadBindingsState().bindingsByAccountConversation.delete(key);
|
||||
persistBindingsSafely({
|
||||
accountId,
|
||||
persist: manager.shouldPersistMutations(),
|
||||
@@ -521,7 +524,7 @@ export function createTelegramThreadBindingManager(
|
||||
accountId,
|
||||
conversationId: entry.conversationId,
|
||||
});
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.delete(key);
|
||||
getThreadBindingsState().bindingsByAccountConversation.delete(key);
|
||||
removed.push(entry);
|
||||
}
|
||||
if (removed.length > 0) {
|
||||
@@ -540,9 +543,9 @@ export function createTelegramThreadBindingManager(
|
||||
sweepTimer = null;
|
||||
}
|
||||
unregisterSessionBindingAdapter({ channel: "telegram", accountId });
|
||||
const existingManager = MANAGERS_BY_ACCOUNT_ID.get(accountId);
|
||||
const existingManager = getThreadBindingsState().managersByAccountId.get(accountId);
|
||||
if (existingManager === manager) {
|
||||
MANAGERS_BY_ACCOUNT_ID.delete(accountId);
|
||||
getThreadBindingsState().managersByAccountId.delete(accountId);
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -574,7 +577,7 @@ export function createTelegramThreadBindingManager(
|
||||
metadata: input.metadata,
|
||||
},
|
||||
});
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.set(
|
||||
getThreadBindingsState().bindingsByAccountConversation.set(
|
||||
resolveBindingKey({ accountId, conversationId }),
|
||||
record,
|
||||
);
|
||||
@@ -714,14 +717,14 @@ export function createTelegramThreadBindingManager(
|
||||
sweepTimer.unref?.();
|
||||
}
|
||||
|
||||
MANAGERS_BY_ACCOUNT_ID.set(accountId, manager);
|
||||
getThreadBindingsState().managersByAccountId.set(accountId, manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
export function getTelegramThreadBindingManager(
|
||||
accountId?: string,
|
||||
): TelegramThreadBindingManager | null {
|
||||
return MANAGERS_BY_ACCOUNT_ID.get(normalizeAccountId(accountId)) ?? null;
|
||||
return getThreadBindingsState().managersByAccountId.get(normalizeAccountId(accountId)) ?? null;
|
||||
}
|
||||
|
||||
function updateTelegramBindingsBySessionKey(params: {
|
||||
@@ -741,7 +744,7 @@ function updateTelegramBindingsBySessionKey(params: {
|
||||
conversationId: entry.conversationId,
|
||||
});
|
||||
const next = params.update(entry, now);
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.set(key, next);
|
||||
getThreadBindingsState().bindingsByAccountConversation.set(key, next);
|
||||
updated.push(next);
|
||||
}
|
||||
if (updated.length > 0) {
|
||||
@@ -799,12 +802,12 @@ export function setTelegramThreadBindingMaxAgeBySessionKey(params: {
|
||||
|
||||
export const __testing = {
|
||||
async resetTelegramThreadBindingsForTests() {
|
||||
for (const manager of MANAGERS_BY_ACCOUNT_ID.values()) {
|
||||
for (const manager of getThreadBindingsState().managersByAccountId.values()) {
|
||||
manager.stop();
|
||||
}
|
||||
await Promise.allSettled(PERSIST_QUEUE_BY_ACCOUNT_ID.values());
|
||||
PERSIST_QUEUE_BY_ACCOUNT_ID.clear();
|
||||
MANAGERS_BY_ACCOUNT_ID.clear();
|
||||
BINDINGS_BY_ACCOUNT_CONVERSATION.clear();
|
||||
await Promise.allSettled(getThreadBindingsState().persistQueueByAccountId.values());
|
||||
getThreadBindingsState().persistQueueByAccountId.clear();
|
||||
getThreadBindingsState().managersByAccountId.clear();
|
||||
getThreadBindingsState().bindingsByAccountConversation.clear();
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user