fix: keep the paired user when the poll loop commits its offset
The poll loop persisted the config object it captured when polling started. The store swaps in a fresh object on every persist, so after the initial sync that captured copy lacked later changes: the next offset commit erased the paired user and the bridge re-paired on every message.
This commit is contained in:
1 parent
033a92f3bb
commit
60254b288b
2 files changed
+47
-1
No files matched your search
+9
-1
@@ -971,7 +971,15 @@ export function createTelegramPollLoopRunner<
|
|||||||
config: deps.getConfig(),
|
config: deps.getConfig(),
|
||||||
deleteWebhook: deps.deleteWebhook,
|
deleteWebhook: deps.deleteWebhook,
|
||||||
getUpdates: deps.getUpdates,
|
getUpdates: deps.getUpdates,
|
||||||
persistConfig: deps.persistConfig,
|
// The loop keeps the config object captured when polling started, but the
|
||||||
|
// store swaps in a fresh object on every persist. Persisting that stale
|
||||||
|
// copy erased later changes such as the paired user, so only the poll
|
||||||
|
// offset is carried onto the store's current config.
|
||||||
|
persistConfig: (polled) => {
|
||||||
|
const current = deps.getConfig();
|
||||||
|
current.lastUpdateId = polled.lastUpdateId;
|
||||||
|
return deps.persistConfig(current);
|
||||||
|
},
|
||||||
handleUpdate: deps.handleUpdate,
|
handleUpdate: deps.handleUpdate,
|
||||||
onErrorStatus: (message) => {
|
onErrorStatus: (message) => {
|
||||||
updateTelegramPollingStatusSafely(deps.updateStatus, ctx, {
|
updateTelegramPollingStatusSafely(deps.updateStatus, ctx, {
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
|
import { mkdtempSync, readFileSync } from "node:fs";
|
||||||
|
import { tmpdir } from "node:os";
|
||||||
|
import { join } from "node:path";
|
||||||
import test from "node:test";
|
import test from "node:test";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -29,6 +32,7 @@ import {
|
|||||||
stopTelegramPollingRuntime,
|
stopTelegramPollingRuntime,
|
||||||
TELEGRAM_ALLOWED_UPDATES,
|
TELEGRAM_ALLOWED_UPDATES,
|
||||||
} from "../lib/polling.ts";
|
} from "../lib/polling.ts";
|
||||||
|
import { createTelegramConfigStore } from "../lib/config.ts";
|
||||||
|
|
||||||
const TEST_CONTEXT = "ctx";
|
const TEST_CONTEXT = "ctx";
|
||||||
|
|
||||||
@@ -601,6 +605,40 @@ test("Poll loop runner binds config, status, and transport ports", async () => {
|
|||||||
assert.deepEqual(events, ["deleteWebhook", "handle:ctx:6", "persist:6"]);
|
assert.deepEqual(events, ["deleteWebhook", "handle:ctx:6", "persist:6"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Poll loop keeps the paired user when the offset is committed after the initial sync replaced the stored config", async () => {
|
||||||
|
const dir = mkdtempSync(join(tmpdir(), "telegram-pairing-"));
|
||||||
|
const configPath = join(dir, "telegram.json");
|
||||||
|
const store = createTelegramConfigStore({ agentDir: dir, configPath });
|
||||||
|
await store.load();
|
||||||
|
store.update((config) => {
|
||||||
|
config.botToken = "123:abc";
|
||||||
|
});
|
||||||
|
await store.persist();
|
||||||
|
let calls = 0;
|
||||||
|
const runPollLoop = createTelegramPollLoopRunner({
|
||||||
|
getConfig: store.get,
|
||||||
|
deleteWebhook: async () => {},
|
||||||
|
getUpdates: async () => {
|
||||||
|
calls += 1;
|
||||||
|
if (calls === 1) return [{ update_id: 1 }]; // initial sync
|
||||||
|
if (calls === 2) return [{ update_id: 2 }]; // the owner's /start
|
||||||
|
throw new DOMException("stop", "AbortError");
|
||||||
|
},
|
||||||
|
persistConfig: store.persist,
|
||||||
|
handleUpdate: async () => {
|
||||||
|
store.setAllowedUserId(777);
|
||||||
|
await store.persist();
|
||||||
|
},
|
||||||
|
updateStatus: () => {},
|
||||||
|
sleep: async () => {},
|
||||||
|
});
|
||||||
|
await runPollLoop("ctx", new AbortController().signal);
|
||||||
|
assert.equal(store.getAllowedUserId(), 777);
|
||||||
|
const saved = JSON.parse(readFileSync(configPath, "utf8"));
|
||||||
|
assert.equal(saved.allowedUserId, 777);
|
||||||
|
assert.equal(saved.lastUpdateId, 2);
|
||||||
|
});
|
||||||
|
|
||||||
test("Poll loop runner ignores stale-context status failures while retrying", async () => {
|
test("Poll loop runner ignores stale-context status failures while retrying", async () => {
|
||||||
const config = { botToken: "123:abc", lastUpdateId: 1 };
|
const config = { botToken: "123:abc", lastUpdateId: 1 };
|
||||||
const events: string[] = [];
|
const events: string[] = [];
|
||||||
|
|||||||
Reference in new issue
Block a user