feat(wechat): add Intent Transaction Layer with unified task schema
Introduce Draft → Confirm → Commit flow for WeChat schedule intents behind feature flags, plus h5_tasks dual-write/read aggregation and rollout scripts so reminders and automations get explicit user confirmation before persisting. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { attachUnifiedTaskSync } from './task-unified-sync.mjs';
|
||||
|
||||
test('attachUnifiedTaskSync wraps scheduled task create when enabled', async () => {
|
||||
const syncCalls = [];
|
||||
const scheduledTaskService = {
|
||||
async createTask(payload) {
|
||||
return {
|
||||
id: 'task-1',
|
||||
userId: payload.userId,
|
||||
title: payload.title,
|
||||
taskSpec: payload.taskSpec,
|
||||
recurrence: 'daily',
|
||||
hour: 6,
|
||||
minute: 0,
|
||||
nextRunAt: 5000,
|
||||
timezone: 'Asia/Shanghai',
|
||||
notifyChannel: 'both',
|
||||
sourceChannel: payload.sourceChannel,
|
||||
};
|
||||
},
|
||||
};
|
||||
const taskUnifiedService = {
|
||||
async syncFromCommit(payload) {
|
||||
syncCalls.push(payload);
|
||||
return { id: 'unified-1' };
|
||||
},
|
||||
};
|
||||
|
||||
attachUnifiedTaskSync({
|
||||
scheduleService: {},
|
||||
scheduledTaskService,
|
||||
taskUnifiedService,
|
||||
pool: { async query() { return [[]]; } },
|
||||
env: { H5_UNIFIED_TASKS_ENABLED: '1' },
|
||||
});
|
||||
|
||||
await scheduledTaskService.createTask({
|
||||
userId: 'user-1',
|
||||
title: '每日新闻',
|
||||
taskSpec: 'news',
|
||||
sourceChannel: 'wechat',
|
||||
});
|
||||
|
||||
assert.equal(syncCalls.length, 1);
|
||||
assert.equal(syncCalls[0].kind, 'scheduled_task');
|
||||
});
|
||||
|
||||
test('attachUnifiedTaskSync syncs lifecycle on markTaskSucceeded', async () => {
|
||||
const lifecycleCalls = [];
|
||||
const scheduledTaskService = {
|
||||
async markTaskSucceeded(task) {
|
||||
return {
|
||||
...task,
|
||||
status: 'active',
|
||||
nextRunAt: 9000,
|
||||
lastRunAt: 8000,
|
||||
};
|
||||
},
|
||||
};
|
||||
attachUnifiedTaskSync({
|
||||
scheduleService: {},
|
||||
scheduledTaskService,
|
||||
taskUnifiedService: {
|
||||
async syncLegacyLifecycle(payload) {
|
||||
lifecycleCalls.push(payload);
|
||||
},
|
||||
},
|
||||
pool: { async query() { return [[]]; } },
|
||||
env: { H5_UNIFIED_TASKS_ENABLED: '1' },
|
||||
});
|
||||
await scheduledTaskService.markTaskSucceeded({
|
||||
id: 'task-1',
|
||||
userId: 'user-1',
|
||||
recurrence: 'daily',
|
||||
});
|
||||
assert.equal(lifecycleCalls.length, 1);
|
||||
assert.equal(lifecycleCalls[0].status, 'active');
|
||||
});
|
||||
|
||||
test('attachUnifiedTaskSync is noop when feature disabled', async () => {
|
||||
const syncCalls = [];
|
||||
const scheduledTaskService = {
|
||||
async createTask() {
|
||||
return { id: 'task-1' };
|
||||
},
|
||||
};
|
||||
attachUnifiedTaskSync({
|
||||
scheduleService: {},
|
||||
scheduledTaskService,
|
||||
taskUnifiedService: {
|
||||
async syncFromCommit() {
|
||||
syncCalls.push(true);
|
||||
},
|
||||
},
|
||||
pool: { async query() { return [[]]; } },
|
||||
env: { H5_UNIFIED_TASKS_ENABLED: '0' },
|
||||
});
|
||||
await scheduledTaskService.createTask({ userId: 'user-1' });
|
||||
assert.equal(syncCalls.length, 0);
|
||||
});
|
||||
Reference in New Issue
Block a user