@develit-services/bank 5.9.2 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base.cjs +16 -185
- package/dist/base.d.cts +1 -7
- package/dist/base.d.mts +1 -7
- package/dist/base.d.ts +1 -7
- package/dist/base.mjs +16 -185
- package/dist/export/workflows.cjs +9 -23
- package/dist/export/workflows.d.cts +0 -1
- package/dist/export/workflows.d.mts +0 -1
- package/dist/export/workflows.d.ts +0 -1
- package/dist/export/workflows.mjs +9 -23
- package/dist/service.d.cts +0 -3
- package/dist/service.d.mts +0 -3
- package/dist/service.d.ts +0 -3
- package/dist/shared/{bank.DAjqsBQN.mjs → bank.BWR4dqQ5.mjs} +1 -28
- package/dist/shared/{bank.DBTtRCcf.cjs → bank.CSmuzdUJ.cjs} +0 -31
- package/package.json +1 -1
package/dist/base.cjs
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
const backendSdk = require('@develit-io/backend-sdk');
|
|
4
4
|
const paymentDirection = require('./shared/bank.BsWBG0gb.cjs');
|
|
5
|
-
const bank = require('./shared/bank.DBTtRCcf.cjs');
|
|
6
5
|
const drizzleOrm = require('drizzle-orm');
|
|
7
6
|
const cloudflare_workers = require('cloudflare:workers');
|
|
8
7
|
const d1 = require('drizzle-orm/d1');
|
|
9
8
|
require('jose');
|
|
9
|
+
const bank = require('./shared/bank.CSmuzdUJ.cjs');
|
|
10
10
|
const zod = require('zod');
|
|
11
11
|
const database_schema = require('./shared/bank.Ca3jzmIb.cjs');
|
|
12
12
|
const generalCodes = require('@develit-io/general-codes');
|
|
@@ -107,25 +107,6 @@ async function heartbeatSyncWorkflows({
|
|
|
107
107
|
);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
const DISPATCH_RECOVERY_WINDOW_MS = 5 * 60 * 1e3;
|
|
111
|
-
function buildDispatchInstanceId(accountId, nowMs, recoveryWindowMs = DISPATCH_RECOVERY_WINDOW_MS) {
|
|
112
|
-
return `${accountId}-${Math.floor(nowMs / recoveryWindowMs)}`;
|
|
113
|
-
}
|
|
114
|
-
function buildDispatchCreateOptions(instanceId, accountId, maxIterations) {
|
|
115
|
-
return {
|
|
116
|
-
id: instanceId,
|
|
117
|
-
// Omitted (not undefined) when unresolved: the workflow treats a missing
|
|
118
|
-
// budget as unbounded — degraded but syncing.
|
|
119
|
-
params: maxIterations == null ? { accountId } : { accountId, maxIterations },
|
|
120
|
-
// Dispatch mints ~24 instances per account per day and step outputs carry
|
|
121
|
-
// bank payloads — the default 30-day retention would pile up billable
|
|
122
|
-
// storage for state nobody reads after success.
|
|
123
|
-
retention: {
|
|
124
|
-
successRetention: "1 day",
|
|
125
|
-
errorRetention: "7 days"
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
110
|
function isAlreadyExists(err) {
|
|
130
111
|
return /already exists/i.test(extractMessage(err));
|
|
131
112
|
}
|
|
@@ -136,64 +117,6 @@ function extractMessage(err) {
|
|
|
136
117
|
return err instanceof Error ? err.message : typeof err === "object" && err !== null && "message" in err ? String(err.message) : "";
|
|
137
118
|
}
|
|
138
119
|
|
|
139
|
-
const DEFAULT_MIN_GRACE_MS = 3 * 60 * 1e3;
|
|
140
|
-
async function dispatchSyncWorkflows({
|
|
141
|
-
entities,
|
|
142
|
-
createInstance,
|
|
143
|
-
logger,
|
|
144
|
-
now = Date.now,
|
|
145
|
-
minGraceMs = DEFAULT_MIN_GRACE_MS,
|
|
146
|
-
recoveryWindowMs = DISPATCH_RECOVERY_WINDOW_MS
|
|
147
|
-
}) {
|
|
148
|
-
const at = now();
|
|
149
|
-
await Promise.all(
|
|
150
|
-
entities.map(async (entity) => {
|
|
151
|
-
const { id, lastSyncAt } = entity;
|
|
152
|
-
const staleness = assessSyncStaleness(entity, at, minGraceMs);
|
|
153
|
-
if (staleness == null) {
|
|
154
|
-
logger.warn("sync-workflow.dispatch.sync-age-unknown", { id });
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (staleness.staleForMs <= staleness.thresholdMs) return;
|
|
158
|
-
const instanceId = buildDispatchInstanceId(id, at, recoveryWindowMs);
|
|
159
|
-
try {
|
|
160
|
-
await createInstance(instanceId, id);
|
|
161
|
-
logger.info("sync-workflow.dispatch.created", {
|
|
162
|
-
id,
|
|
163
|
-
instanceId,
|
|
164
|
-
lastSyncAt: lastSyncAt?.toISOString() ?? null,
|
|
165
|
-
staleForS: Math.round(staleness.staleForMs / 1e3),
|
|
166
|
-
thresholdS: Math.round(staleness.thresholdMs / 1e3)
|
|
167
|
-
});
|
|
168
|
-
} catch (err) {
|
|
169
|
-
if (isAlreadyExists(err)) {
|
|
170
|
-
logger.info("sync-workflow.dispatch.already-running", {
|
|
171
|
-
id,
|
|
172
|
-
instanceId
|
|
173
|
-
});
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
logger.error("sync-workflow.dispatch.failed", {
|
|
177
|
-
id,
|
|
178
|
-
instanceId,
|
|
179
|
-
error: err instanceof Error ? err.message : String(err)
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
})
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function isDispatchEnabled(accountId, selection) {
|
|
187
|
-
const raw = selection?.trim();
|
|
188
|
-
if (!raw) return false;
|
|
189
|
-
if (raw.toLowerCase() === "all") return true;
|
|
190
|
-
return raw.split(",").map((id) => id.trim()).includes(accountId);
|
|
191
|
-
}
|
|
192
|
-
function isDispatchActive(accountId, selection, dispatchCron) {
|
|
193
|
-
if (!dispatchCron?.trim()) return false;
|
|
194
|
-
return isDispatchEnabled(accountId, selection);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
120
|
const FINITE_STATUSES = /* @__PURE__ */ new Set([
|
|
198
121
|
"complete",
|
|
199
122
|
"errored",
|
|
@@ -1028,35 +951,18 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
|
|
|
1028
951
|
{ successMessage: "Account sync workflow started" },
|
|
1029
952
|
async ({ accountId }) => {
|
|
1030
953
|
await this.setSyncEnabledOrThrow(accountId, true);
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
this.env.
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
instance2 = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.create(
|
|
1043
|
-
buildDispatchCreateOptions(instanceId, accountId, maxIterations)
|
|
1044
|
-
);
|
|
1045
|
-
} catch (err) {
|
|
1046
|
-
if (!isAlreadyExists(err)) throw err;
|
|
1047
|
-
instance2 = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(instanceId);
|
|
1048
|
-
}
|
|
1049
|
-
return {
|
|
1050
|
-
instanceId: instance2.id,
|
|
1051
|
-
details: await instance2.status()
|
|
1052
|
-
};
|
|
954
|
+
let instance;
|
|
955
|
+
try {
|
|
956
|
+
instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.create({
|
|
957
|
+
id: accountId,
|
|
958
|
+
params: {
|
|
959
|
+
accountId
|
|
960
|
+
}
|
|
961
|
+
});
|
|
962
|
+
} catch (err) {
|
|
963
|
+
if (!isAlreadyExists(err)) throw err;
|
|
964
|
+
instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(accountId);
|
|
1053
965
|
}
|
|
1054
|
-
const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.create({
|
|
1055
|
-
id: accountId,
|
|
1056
|
-
params: {
|
|
1057
|
-
accountId
|
|
1058
|
-
}
|
|
1059
|
-
});
|
|
1060
966
|
return {
|
|
1061
967
|
instanceId: instance.id,
|
|
1062
968
|
details: await instance.status()
|
|
@@ -1083,30 +989,6 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
|
|
|
1083
989
|
{ successMessage: "Account sync workflow restarted" },
|
|
1084
990
|
async ({ accountId }) => {
|
|
1085
991
|
await this.setSyncEnabledOrThrow(accountId, true);
|
|
1086
|
-
if (isDispatchActive(
|
|
1087
|
-
accountId,
|
|
1088
|
-
this.env.SYNC_DISPATCH_ACCOUNT_IDS,
|
|
1089
|
-
this.env.CRON_SYNC_WORKFLOW_DISPATCH
|
|
1090
|
-
)) {
|
|
1091
|
-
const instanceId = buildDispatchInstanceId(accountId, Date.now());
|
|
1092
|
-
const maxIterations = bank.parseIterationBudgetParam(
|
|
1093
|
-
this.env.SYNC_WORKFLOW_MAX_ITERATIONS
|
|
1094
|
-
);
|
|
1095
|
-
let instance2;
|
|
1096
|
-
try {
|
|
1097
|
-
instance2 = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.create(
|
|
1098
|
-
buildDispatchCreateOptions(instanceId, accountId, maxIterations)
|
|
1099
|
-
);
|
|
1100
|
-
} catch (err) {
|
|
1101
|
-
if (!isAlreadyExists(err)) throw err;
|
|
1102
|
-
instance2 = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(instanceId);
|
|
1103
|
-
await instance2.restart();
|
|
1104
|
-
}
|
|
1105
|
-
return {
|
|
1106
|
-
instanceId: instance2.id,
|
|
1107
|
-
details: await instance2.status()
|
|
1108
|
-
};
|
|
1109
|
-
}
|
|
1110
992
|
let instance;
|
|
1111
993
|
try {
|
|
1112
994
|
const existing = await this.getCurrentSyncInstance(accountId);
|
|
@@ -1423,19 +1305,11 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
|
|
|
1423
1305
|
console.log("Scheduled CRON payment request statuses");
|
|
1424
1306
|
await this.updatePaymentRequestStatuses();
|
|
1425
1307
|
}
|
|
1426
|
-
if (controller.cron === this.env.CRON_SYNC_WORKFLOW_DISPATCH) {
|
|
1427
|
-
await this.dispatchSyncWorkflows();
|
|
1428
|
-
}
|
|
1429
1308
|
if (controller.cron === this.env.CRON_SYNC_WORKFLOW_HEARTBEAT) {
|
|
1430
1309
|
console.log("Scheduled CRON sync workflow heartbeat");
|
|
1431
1310
|
await this.heartbeatSyncWorkflows();
|
|
1432
1311
|
}
|
|
1433
1312
|
}
|
|
1434
|
-
/**
|
|
1435
|
-
* Lifecycle actions must target the instance that actually syncs the
|
|
1436
|
-
* account — under dispatch that is the windowed instance recorded with the
|
|
1437
|
-
* last sync write, not the legacy canonical id.
|
|
1438
|
-
*/
|
|
1439
1313
|
async setSyncEnabledOrThrow(accountId, syncEnabled) {
|
|
1440
1314
|
const [updated] = await updateAccountSyncEnabledCommand(this.db, {
|
|
1441
1315
|
accountId,
|
|
@@ -1446,34 +1320,7 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
|
|
|
1446
1320
|
}
|
|
1447
1321
|
}
|
|
1448
1322
|
async getCurrentSyncInstance(accountId) {
|
|
1449
|
-
|
|
1450
|
-
return this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(
|
|
1451
|
-
bank.resolveCurrentSyncInstanceId(
|
|
1452
|
-
accountId,
|
|
1453
|
-
account?.lastSyncMetadata?.instanceId
|
|
1454
|
-
)
|
|
1455
|
-
);
|
|
1456
|
-
}
|
|
1457
|
-
async dispatchSyncWorkflows() {
|
|
1458
|
-
const selection = this.env.SYNC_DISPATCH_ACCOUNT_IDS;
|
|
1459
|
-
if (!selection?.trim()) return;
|
|
1460
|
-
const accounts = await getSyncCandidateAccountsQuery(this.db);
|
|
1461
|
-
const maxIterations = bank.parseIterationBudgetParam(
|
|
1462
|
-
this.env.SYNC_WORKFLOW_MAX_ITERATIONS
|
|
1463
|
-
);
|
|
1464
|
-
if (maxIterations == null) {
|
|
1465
|
-
syncEventConsoleLogger.error(
|
|
1466
|
-
"sync-workflow.dispatch.invalid-max-iterations",
|
|
1467
|
-
{ value: this.env.SYNC_WORKFLOW_MAX_ITERATIONS }
|
|
1468
|
-
);
|
|
1469
|
-
}
|
|
1470
|
-
await dispatchSyncWorkflows({
|
|
1471
|
-
entities: accounts.filter((a) => isDispatchEnabled(a.id, selection)),
|
|
1472
|
-
createInstance: (instanceId, accountId) => this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.create(
|
|
1473
|
-
buildDispatchCreateOptions(instanceId, accountId, maxIterations)
|
|
1474
|
-
),
|
|
1475
|
-
logger: syncEventConsoleLogger
|
|
1476
|
-
});
|
|
1323
|
+
return this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(accountId);
|
|
1477
1324
|
}
|
|
1478
1325
|
async heartbeatSyncWorkflows() {
|
|
1479
1326
|
const accounts = await getSyncCandidateAccountsQuery(this.db);
|
|
@@ -1488,13 +1335,7 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
|
|
|
1488
1335
|
return;
|
|
1489
1336
|
}
|
|
1490
1337
|
await heartbeatSyncWorkflows({
|
|
1491
|
-
entities: accounts.
|
|
1492
|
-
(a) => !isDispatchActive(
|
|
1493
|
-
a.id,
|
|
1494
|
-
this.env.SYNC_DISPATCH_ACCOUNT_IDS,
|
|
1495
|
-
this.env.CRON_SYNC_WORKFLOW_DISPATCH
|
|
1496
|
-
)
|
|
1497
|
-
).map((a) => ({
|
|
1338
|
+
entities: accounts.map((a) => ({
|
|
1498
1339
|
id: a.id,
|
|
1499
1340
|
iterationCount: a.lastSyncMetadata?.iterationCount,
|
|
1500
1341
|
syncIntervalS: a.syncIntervalS,
|
|
@@ -2266,12 +2107,7 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
|
|
|
2266
2107
|
if (includeWorkflow) {
|
|
2267
2108
|
let status;
|
|
2268
2109
|
try {
|
|
2269
|
-
const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(
|
|
2270
|
-
bank.resolveCurrentSyncInstanceId(
|
|
2271
|
-
a.id,
|
|
2272
|
-
a.lastSyncMetadata?.instanceId
|
|
2273
|
-
)
|
|
2274
|
-
);
|
|
2110
|
+
const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(a.id);
|
|
2275
2111
|
status = await instance.status();
|
|
2276
2112
|
} catch (_) {
|
|
2277
2113
|
status = null;
|
|
@@ -2371,12 +2207,7 @@ exports.BankServiceBase = class BankServiceBase extends backendSdk.develitWorker
|
|
|
2371
2207
|
throw accountNotFoundError();
|
|
2372
2208
|
}
|
|
2373
2209
|
try {
|
|
2374
|
-
const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(
|
|
2375
|
-
bank.resolveCurrentSyncInstanceId(
|
|
2376
|
-
accountId,
|
|
2377
|
-
account.lastSyncMetadata?.instanceId
|
|
2378
|
-
)
|
|
2379
|
-
);
|
|
2210
|
+
const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(accountId);
|
|
2380
2211
|
await terminateSyncWorkflow(instance);
|
|
2381
2212
|
} catch (error) {
|
|
2382
2213
|
this.log({
|
package/dist/base.d.cts
CHANGED
|
@@ -2699,9 +2699,9 @@ declare const getBatchesInputSchema: z.ZodObject<{
|
|
|
2699
2699
|
limit: z.ZodNumber;
|
|
2700
2700
|
sort: z.ZodObject<{
|
|
2701
2701
|
column: z.ZodEnum<{
|
|
2702
|
-
batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
|
|
2703
2702
|
createdAt: "createdAt";
|
|
2704
2703
|
updatedAt: "updatedAt";
|
|
2704
|
+
batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
|
|
2705
2705
|
}>;
|
|
2706
2706
|
direction: z.ZodEnum<{
|
|
2707
2707
|
asc: "asc";
|
|
@@ -4212,14 +4212,8 @@ declare class BankServiceBase extends BankServiceBase_base {
|
|
|
4212
4212
|
statusChanged: number;
|
|
4213
4213
|
}>>;
|
|
4214
4214
|
scheduled(controller: ScheduledController): Promise<void>;
|
|
4215
|
-
/**
|
|
4216
|
-
* Lifecycle actions must target the instance that actually syncs the
|
|
4217
|
-
* account — under dispatch that is the windowed instance recorded with the
|
|
4218
|
-
* last sync write, not the legacy canonical id.
|
|
4219
|
-
*/
|
|
4220
4215
|
private setSyncEnabledOrThrow;
|
|
4221
4216
|
private getCurrentSyncInstance;
|
|
4222
|
-
private dispatchSyncWorkflows;
|
|
4223
4217
|
private heartbeatSyncWorkflows;
|
|
4224
4218
|
handleAuthorizationCallback(input: HandleAuthorizationCallbackInput): Promise<IRPCResponse<HandleAuthorizationCallbackOutput>>;
|
|
4225
4219
|
closePaymentRequest(input: ClosePaymentRequestInput): Promise<IRPCResponse<ClosePaymentRequestOutput>>;
|
package/dist/base.d.mts
CHANGED
|
@@ -2699,9 +2699,9 @@ declare const getBatchesInputSchema: z.ZodObject<{
|
|
|
2699
2699
|
limit: z.ZodNumber;
|
|
2700
2700
|
sort: z.ZodObject<{
|
|
2701
2701
|
column: z.ZodEnum<{
|
|
2702
|
-
batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
|
|
2703
2702
|
createdAt: "createdAt";
|
|
2704
2703
|
updatedAt: "updatedAt";
|
|
2704
|
+
batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
|
|
2705
2705
|
}>;
|
|
2706
2706
|
direction: z.ZodEnum<{
|
|
2707
2707
|
asc: "asc";
|
|
@@ -4212,14 +4212,8 @@ declare class BankServiceBase extends BankServiceBase_base {
|
|
|
4212
4212
|
statusChanged: number;
|
|
4213
4213
|
}>>;
|
|
4214
4214
|
scheduled(controller: ScheduledController): Promise<void>;
|
|
4215
|
-
/**
|
|
4216
|
-
* Lifecycle actions must target the instance that actually syncs the
|
|
4217
|
-
* account — under dispatch that is the windowed instance recorded with the
|
|
4218
|
-
* last sync write, not the legacy canonical id.
|
|
4219
|
-
*/
|
|
4220
4215
|
private setSyncEnabledOrThrow;
|
|
4221
4216
|
private getCurrentSyncInstance;
|
|
4222
|
-
private dispatchSyncWorkflows;
|
|
4223
4217
|
private heartbeatSyncWorkflows;
|
|
4224
4218
|
handleAuthorizationCallback(input: HandleAuthorizationCallbackInput): Promise<IRPCResponse<HandleAuthorizationCallbackOutput>>;
|
|
4225
4219
|
closePaymentRequest(input: ClosePaymentRequestInput): Promise<IRPCResponse<ClosePaymentRequestOutput>>;
|
package/dist/base.d.ts
CHANGED
|
@@ -2699,9 +2699,9 @@ declare const getBatchesInputSchema: z.ZodObject<{
|
|
|
2699
2699
|
limit: z.ZodNumber;
|
|
2700
2700
|
sort: z.ZodObject<{
|
|
2701
2701
|
column: z.ZodEnum<{
|
|
2702
|
-
batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
|
|
2703
2702
|
createdAt: "createdAt";
|
|
2704
2703
|
updatedAt: "updatedAt";
|
|
2704
|
+
batchPaymentInitiatedAt: "batchPaymentInitiatedAt";
|
|
2705
2705
|
}>;
|
|
2706
2706
|
direction: z.ZodEnum<{
|
|
2707
2707
|
asc: "asc";
|
|
@@ -4212,14 +4212,8 @@ declare class BankServiceBase extends BankServiceBase_base {
|
|
|
4212
4212
|
statusChanged: number;
|
|
4213
4213
|
}>>;
|
|
4214
4214
|
scheduled(controller: ScheduledController): Promise<void>;
|
|
4215
|
-
/**
|
|
4216
|
-
* Lifecycle actions must target the instance that actually syncs the
|
|
4217
|
-
* account — under dispatch that is the windowed instance recorded with the
|
|
4218
|
-
* last sync write, not the legacy canonical id.
|
|
4219
|
-
*/
|
|
4220
4215
|
private setSyncEnabledOrThrow;
|
|
4221
4216
|
private getCurrentSyncInstance;
|
|
4222
|
-
private dispatchSyncWorkflows;
|
|
4223
4217
|
private heartbeatSyncWorkflows;
|
|
4224
4218
|
handleAuthorizationCallback(input: HandleAuthorizationCallbackInput): Promise<IRPCResponse<HandleAuthorizationCallbackOutput>>;
|
|
4225
4219
|
closePaymentRequest(input: ClosePaymentRequestInput): Promise<IRPCResponse<ClosePaymentRequestOutput>>;
|
package/dist/base.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { uuidv4, first, buildMultiFilterConditions as buildMultiFilterConditions$1, bankAccountMetadataSchema, structuredAddressSchema, workflowInstanceStatusSchema, develitWorker, createInternalError, action, service } from '@develit-io/backend-sdk';
|
|
2
2
|
import { G as tables, g as accountInsertSchema, H as relations, o as isProcessedStatus, p as isTerminalStatus, L as getNonTerminalPaymentRequestsQuery, x as toIncomingPayment, N as calculateCzechIban, j as assignAccount, u as toBatchedPayment, y as toPaymentRequestInsert, a as FinbricksClient, F as FINBRICKS_ENDPOINTS } from './shared/bank.kz-PKVi5.mjs';
|
|
3
|
-
import { j as encrypt, d as createCredentialsResolver, i as initiateConnector, p as parseIterationBudgetParam, e as updatePaymentRequestStatusCommand, a as getPaymentRequestsByBatchIdQuery, g as getBatchByIdQuery, u as upsertBatchCommand, b as getAccountByIdQuery, k as resolveCurrentSyncInstanceId, l as importAesKey, h as createPaymentCommand } from './shared/bank.DAjqsBQN.mjs';
|
|
4
3
|
import { eq, sql, and, like, asc, desc, inArray, gte, lte, isNull, count } from 'drizzle-orm';
|
|
5
4
|
import { WorkerEntrypoint } from 'cloudflare:workers';
|
|
6
5
|
import { drizzle } from 'drizzle-orm/d1';
|
|
7
6
|
import 'jose';
|
|
7
|
+
import { h as encrypt, d as createCredentialsResolver, i as initiateConnector, e as updatePaymentRequestStatusCommand, a as getPaymentRequestsByBatchIdQuery, g as getBatchByIdQuery, u as upsertBatchCommand, j as importAesKey, f as createPaymentCommand, b as getAccountByIdQuery } from './shared/bank.BWR4dqQ5.mjs';
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
import { I as INSTRUCTION_PRIORITIES, C as CHARGE_BEARERS, g as PAYMENT_TYPES, b as CONNECTOR_KEYS, a as BATCH_STATUSES, f as PAYMENT_STATUSES, P as PAYMENT_DIRECTIONS, e as PAYMENT_REQUEST_STATUSES } from './shared/bank.BT7HayCV.mjs';
|
|
10
10
|
import { CURRENCY_CODES } from '@develit-io/general-codes';
|
|
@@ -105,25 +105,6 @@ async function heartbeatSyncWorkflows({
|
|
|
105
105
|
);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
const DISPATCH_RECOVERY_WINDOW_MS = 5 * 60 * 1e3;
|
|
109
|
-
function buildDispatchInstanceId(accountId, nowMs, recoveryWindowMs = DISPATCH_RECOVERY_WINDOW_MS) {
|
|
110
|
-
return `${accountId}-${Math.floor(nowMs / recoveryWindowMs)}`;
|
|
111
|
-
}
|
|
112
|
-
function buildDispatchCreateOptions(instanceId, accountId, maxIterations) {
|
|
113
|
-
return {
|
|
114
|
-
id: instanceId,
|
|
115
|
-
// Omitted (not undefined) when unresolved: the workflow treats a missing
|
|
116
|
-
// budget as unbounded — degraded but syncing.
|
|
117
|
-
params: maxIterations == null ? { accountId } : { accountId, maxIterations },
|
|
118
|
-
// Dispatch mints ~24 instances per account per day and step outputs carry
|
|
119
|
-
// bank payloads — the default 30-day retention would pile up billable
|
|
120
|
-
// storage for state nobody reads after success.
|
|
121
|
-
retention: {
|
|
122
|
-
successRetention: "1 day",
|
|
123
|
-
errorRetention: "7 days"
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
108
|
function isAlreadyExists(err) {
|
|
128
109
|
return /already exists/i.test(extractMessage(err));
|
|
129
110
|
}
|
|
@@ -134,64 +115,6 @@ function extractMessage(err) {
|
|
|
134
115
|
return err instanceof Error ? err.message : typeof err === "object" && err !== null && "message" in err ? String(err.message) : "";
|
|
135
116
|
}
|
|
136
117
|
|
|
137
|
-
const DEFAULT_MIN_GRACE_MS = 3 * 60 * 1e3;
|
|
138
|
-
async function dispatchSyncWorkflows({
|
|
139
|
-
entities,
|
|
140
|
-
createInstance,
|
|
141
|
-
logger,
|
|
142
|
-
now = Date.now,
|
|
143
|
-
minGraceMs = DEFAULT_MIN_GRACE_MS,
|
|
144
|
-
recoveryWindowMs = DISPATCH_RECOVERY_WINDOW_MS
|
|
145
|
-
}) {
|
|
146
|
-
const at = now();
|
|
147
|
-
await Promise.all(
|
|
148
|
-
entities.map(async (entity) => {
|
|
149
|
-
const { id, lastSyncAt } = entity;
|
|
150
|
-
const staleness = assessSyncStaleness(entity, at, minGraceMs);
|
|
151
|
-
if (staleness == null) {
|
|
152
|
-
logger.warn("sync-workflow.dispatch.sync-age-unknown", { id });
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
if (staleness.staleForMs <= staleness.thresholdMs) return;
|
|
156
|
-
const instanceId = buildDispatchInstanceId(id, at, recoveryWindowMs);
|
|
157
|
-
try {
|
|
158
|
-
await createInstance(instanceId, id);
|
|
159
|
-
logger.info("sync-workflow.dispatch.created", {
|
|
160
|
-
id,
|
|
161
|
-
instanceId,
|
|
162
|
-
lastSyncAt: lastSyncAt?.toISOString() ?? null,
|
|
163
|
-
staleForS: Math.round(staleness.staleForMs / 1e3),
|
|
164
|
-
thresholdS: Math.round(staleness.thresholdMs / 1e3)
|
|
165
|
-
});
|
|
166
|
-
} catch (err) {
|
|
167
|
-
if (isAlreadyExists(err)) {
|
|
168
|
-
logger.info("sync-workflow.dispatch.already-running", {
|
|
169
|
-
id,
|
|
170
|
-
instanceId
|
|
171
|
-
});
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
logger.error("sync-workflow.dispatch.failed", {
|
|
175
|
-
id,
|
|
176
|
-
instanceId,
|
|
177
|
-
error: err instanceof Error ? err.message : String(err)
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
})
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function isDispatchEnabled(accountId, selection) {
|
|
185
|
-
const raw = selection?.trim();
|
|
186
|
-
if (!raw) return false;
|
|
187
|
-
if (raw.toLowerCase() === "all") return true;
|
|
188
|
-
return raw.split(",").map((id) => id.trim()).includes(accountId);
|
|
189
|
-
}
|
|
190
|
-
function isDispatchActive(accountId, selection, dispatchCron) {
|
|
191
|
-
if (!dispatchCron?.trim()) return false;
|
|
192
|
-
return isDispatchEnabled(accountId, selection);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
118
|
const FINITE_STATUSES = /* @__PURE__ */ new Set([
|
|
196
119
|
"complete",
|
|
197
120
|
"errored",
|
|
@@ -1026,35 +949,18 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
|
|
|
1026
949
|
{ successMessage: "Account sync workflow started" },
|
|
1027
950
|
async ({ accountId }) => {
|
|
1028
951
|
await this.setSyncEnabledOrThrow(accountId, true);
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
this.env.
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
instance2 = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.create(
|
|
1041
|
-
buildDispatchCreateOptions(instanceId, accountId, maxIterations)
|
|
1042
|
-
);
|
|
1043
|
-
} catch (err) {
|
|
1044
|
-
if (!isAlreadyExists(err)) throw err;
|
|
1045
|
-
instance2 = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(instanceId);
|
|
1046
|
-
}
|
|
1047
|
-
return {
|
|
1048
|
-
instanceId: instance2.id,
|
|
1049
|
-
details: await instance2.status()
|
|
1050
|
-
};
|
|
952
|
+
let instance;
|
|
953
|
+
try {
|
|
954
|
+
instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.create({
|
|
955
|
+
id: accountId,
|
|
956
|
+
params: {
|
|
957
|
+
accountId
|
|
958
|
+
}
|
|
959
|
+
});
|
|
960
|
+
} catch (err) {
|
|
961
|
+
if (!isAlreadyExists(err)) throw err;
|
|
962
|
+
instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(accountId);
|
|
1051
963
|
}
|
|
1052
|
-
const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.create({
|
|
1053
|
-
id: accountId,
|
|
1054
|
-
params: {
|
|
1055
|
-
accountId
|
|
1056
|
-
}
|
|
1057
|
-
});
|
|
1058
964
|
return {
|
|
1059
965
|
instanceId: instance.id,
|
|
1060
966
|
details: await instance.status()
|
|
@@ -1081,30 +987,6 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
|
|
|
1081
987
|
{ successMessage: "Account sync workflow restarted" },
|
|
1082
988
|
async ({ accountId }) => {
|
|
1083
989
|
await this.setSyncEnabledOrThrow(accountId, true);
|
|
1084
|
-
if (isDispatchActive(
|
|
1085
|
-
accountId,
|
|
1086
|
-
this.env.SYNC_DISPATCH_ACCOUNT_IDS,
|
|
1087
|
-
this.env.CRON_SYNC_WORKFLOW_DISPATCH
|
|
1088
|
-
)) {
|
|
1089
|
-
const instanceId = buildDispatchInstanceId(accountId, Date.now());
|
|
1090
|
-
const maxIterations = parseIterationBudgetParam(
|
|
1091
|
-
this.env.SYNC_WORKFLOW_MAX_ITERATIONS
|
|
1092
|
-
);
|
|
1093
|
-
let instance2;
|
|
1094
|
-
try {
|
|
1095
|
-
instance2 = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.create(
|
|
1096
|
-
buildDispatchCreateOptions(instanceId, accountId, maxIterations)
|
|
1097
|
-
);
|
|
1098
|
-
} catch (err) {
|
|
1099
|
-
if (!isAlreadyExists(err)) throw err;
|
|
1100
|
-
instance2 = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(instanceId);
|
|
1101
|
-
await instance2.restart();
|
|
1102
|
-
}
|
|
1103
|
-
return {
|
|
1104
|
-
instanceId: instance2.id,
|
|
1105
|
-
details: await instance2.status()
|
|
1106
|
-
};
|
|
1107
|
-
}
|
|
1108
990
|
let instance;
|
|
1109
991
|
try {
|
|
1110
992
|
const existing = await this.getCurrentSyncInstance(accountId);
|
|
@@ -1421,19 +1303,11 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
|
|
|
1421
1303
|
console.log("Scheduled CRON payment request statuses");
|
|
1422
1304
|
await this.updatePaymentRequestStatuses();
|
|
1423
1305
|
}
|
|
1424
|
-
if (controller.cron === this.env.CRON_SYNC_WORKFLOW_DISPATCH) {
|
|
1425
|
-
await this.dispatchSyncWorkflows();
|
|
1426
|
-
}
|
|
1427
1306
|
if (controller.cron === this.env.CRON_SYNC_WORKFLOW_HEARTBEAT) {
|
|
1428
1307
|
console.log("Scheduled CRON sync workflow heartbeat");
|
|
1429
1308
|
await this.heartbeatSyncWorkflows();
|
|
1430
1309
|
}
|
|
1431
1310
|
}
|
|
1432
|
-
/**
|
|
1433
|
-
* Lifecycle actions must target the instance that actually syncs the
|
|
1434
|
-
* account — under dispatch that is the windowed instance recorded with the
|
|
1435
|
-
* last sync write, not the legacy canonical id.
|
|
1436
|
-
*/
|
|
1437
1311
|
async setSyncEnabledOrThrow(accountId, syncEnabled) {
|
|
1438
1312
|
const [updated] = await updateAccountSyncEnabledCommand(this.db, {
|
|
1439
1313
|
accountId,
|
|
@@ -1444,34 +1318,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
|
|
|
1444
1318
|
}
|
|
1445
1319
|
}
|
|
1446
1320
|
async getCurrentSyncInstance(accountId) {
|
|
1447
|
-
|
|
1448
|
-
return this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(
|
|
1449
|
-
resolveCurrentSyncInstanceId(
|
|
1450
|
-
accountId,
|
|
1451
|
-
account?.lastSyncMetadata?.instanceId
|
|
1452
|
-
)
|
|
1453
|
-
);
|
|
1454
|
-
}
|
|
1455
|
-
async dispatchSyncWorkflows() {
|
|
1456
|
-
const selection = this.env.SYNC_DISPATCH_ACCOUNT_IDS;
|
|
1457
|
-
if (!selection?.trim()) return;
|
|
1458
|
-
const accounts = await getSyncCandidateAccountsQuery(this.db);
|
|
1459
|
-
const maxIterations = parseIterationBudgetParam(
|
|
1460
|
-
this.env.SYNC_WORKFLOW_MAX_ITERATIONS
|
|
1461
|
-
);
|
|
1462
|
-
if (maxIterations == null) {
|
|
1463
|
-
syncEventConsoleLogger.error(
|
|
1464
|
-
"sync-workflow.dispatch.invalid-max-iterations",
|
|
1465
|
-
{ value: this.env.SYNC_WORKFLOW_MAX_ITERATIONS }
|
|
1466
|
-
);
|
|
1467
|
-
}
|
|
1468
|
-
await dispatchSyncWorkflows({
|
|
1469
|
-
entities: accounts.filter((a) => isDispatchEnabled(a.id, selection)),
|
|
1470
|
-
createInstance: (instanceId, accountId) => this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.create(
|
|
1471
|
-
buildDispatchCreateOptions(instanceId, accountId, maxIterations)
|
|
1472
|
-
),
|
|
1473
|
-
logger: syncEventConsoleLogger
|
|
1474
|
-
});
|
|
1321
|
+
return this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(accountId);
|
|
1475
1322
|
}
|
|
1476
1323
|
async heartbeatSyncWorkflows() {
|
|
1477
1324
|
const accounts = await getSyncCandidateAccountsQuery(this.db);
|
|
@@ -1486,13 +1333,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
|
|
|
1486
1333
|
return;
|
|
1487
1334
|
}
|
|
1488
1335
|
await heartbeatSyncWorkflows({
|
|
1489
|
-
entities: accounts.
|
|
1490
|
-
(a) => !isDispatchActive(
|
|
1491
|
-
a.id,
|
|
1492
|
-
this.env.SYNC_DISPATCH_ACCOUNT_IDS,
|
|
1493
|
-
this.env.CRON_SYNC_WORKFLOW_DISPATCH
|
|
1494
|
-
)
|
|
1495
|
-
).map((a) => ({
|
|
1336
|
+
entities: accounts.map((a) => ({
|
|
1496
1337
|
id: a.id,
|
|
1497
1338
|
iterationCount: a.lastSyncMetadata?.iterationCount,
|
|
1498
1339
|
syncIntervalS: a.syncIntervalS,
|
|
@@ -2264,12 +2105,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
|
|
|
2264
2105
|
if (includeWorkflow) {
|
|
2265
2106
|
let status;
|
|
2266
2107
|
try {
|
|
2267
|
-
const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(
|
|
2268
|
-
resolveCurrentSyncInstanceId(
|
|
2269
|
-
a.id,
|
|
2270
|
-
a.lastSyncMetadata?.instanceId
|
|
2271
|
-
)
|
|
2272
|
-
);
|
|
2108
|
+
const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(a.id);
|
|
2273
2109
|
status = await instance.status();
|
|
2274
2110
|
} catch (_) {
|
|
2275
2111
|
status = null;
|
|
@@ -2369,12 +2205,7 @@ let BankServiceBase = class extends develitWorker(WorkerEntrypoint) {
|
|
|
2369
2205
|
throw accountNotFoundError();
|
|
2370
2206
|
}
|
|
2371
2207
|
try {
|
|
2372
|
-
const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(
|
|
2373
|
-
resolveCurrentSyncInstanceId(
|
|
2374
|
-
accountId,
|
|
2375
|
-
account.lastSyncMetadata?.instanceId
|
|
2376
|
-
)
|
|
2377
|
-
);
|
|
2208
|
+
const instance = await this.env.SYNC_ACCOUNT_PAYMENTS_WORKFLOW.get(accountId);
|
|
2378
2209
|
await terminateSyncWorkflow(instance);
|
|
2379
2210
|
} catch (error) {
|
|
2380
2211
|
this.log({
|
|
@@ -4,7 +4,7 @@ const backendSdk = require('@develit-io/backend-sdk');
|
|
|
4
4
|
const paymentDirection = require('../shared/bank.BsWBG0gb.cjs');
|
|
5
5
|
const batchLifecycle = require('../shared/bank.NF8bZBy0.cjs');
|
|
6
6
|
const drizzleOrm = require('drizzle-orm');
|
|
7
|
-
const bank = require('../shared/bank.
|
|
7
|
+
const bank = require('../shared/bank.CSmuzdUJ.cjs');
|
|
8
8
|
const cloudflare_workers = require('cloudflare:workers');
|
|
9
9
|
const cloudflare_workflows = require('cloudflare:workflows');
|
|
10
10
|
const d1 = require('drizzle-orm/d1');
|
|
@@ -425,8 +425,7 @@ async function pushToQueue(queue, message) {
|
|
|
425
425
|
}
|
|
426
426
|
class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
|
|
427
427
|
async run(event, step) {
|
|
428
|
-
const { accountId
|
|
429
|
-
const iterationBudget = bank.resolveIterationBudget(maxIterations);
|
|
428
|
+
const { accountId } = event.payload;
|
|
430
429
|
const db = d1.drizzle(this.env.BANK_D1, { schema: paymentDirection.tables, relations: paymentDirection.relations });
|
|
431
430
|
const logger = createWorkflowLogger(event.instanceId);
|
|
432
431
|
if (!accountId) {
|
|
@@ -436,7 +435,7 @@ class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
|
|
|
436
435
|
"capture workflow start time",
|
|
437
436
|
async () => Date.now()
|
|
438
437
|
);
|
|
439
|
-
for (let iteration = 0;
|
|
438
|
+
for (let iteration = 0; ; iteration++) {
|
|
440
439
|
const account = await step.do("load account", async () => {
|
|
441
440
|
const account2 = await bank.getAccountByIdQuery(db, { accountId });
|
|
442
441
|
if (!account2) {
|
|
@@ -455,19 +454,6 @@ class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
|
|
|
455
454
|
if (!account.lastSyncAt) {
|
|
456
455
|
throw new Error(`lastSyncedAt is not set for account: ${accountId}`);
|
|
457
456
|
}
|
|
458
|
-
if (bank.isSupersededBy(
|
|
459
|
-
event.instanceId,
|
|
460
|
-
account.lastSyncMetadata?.instanceId,
|
|
461
|
-
accountId
|
|
462
|
-
)) {
|
|
463
|
-
logger.info("sync.superseded", {
|
|
464
|
-
accountId,
|
|
465
|
-
instanceId: event.instanceId,
|
|
466
|
-
supersededBy: account.lastSyncMetadata?.instanceId,
|
|
467
|
-
iteration
|
|
468
|
-
});
|
|
469
|
-
return;
|
|
470
|
-
}
|
|
471
457
|
const lastSyncAtMs = account.lastSyncAt.getTime();
|
|
472
458
|
const windowMs = await step.do("resolve sync window", async () => {
|
|
473
459
|
const window = resolveSyncWindow(
|
|
@@ -695,6 +681,12 @@ class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
|
|
|
695
681
|
lastSyncMetadata,
|
|
696
682
|
seenInstanceId: account.lastSyncMetadata?.instanceId ?? null
|
|
697
683
|
}).command;
|
|
684
|
+
if (eventsToEmit.length) {
|
|
685
|
+
await pushToQueue(
|
|
686
|
+
this.env.QUEUE_BUS_QUEUE,
|
|
687
|
+
eventsToEmit
|
|
688
|
+
);
|
|
689
|
+
}
|
|
698
690
|
let syncStateRows;
|
|
699
691
|
if (createCommands.length) {
|
|
700
692
|
const [updateResult] = await db.batch(
|
|
@@ -710,12 +702,6 @@ class BankSyncAccountPayments extends cloudflare_workers.WorkflowEntrypoint {
|
|
|
710
702
|
instanceId: event.instanceId
|
|
711
703
|
});
|
|
712
704
|
}
|
|
713
|
-
if (eventsToEmit.length) {
|
|
714
|
-
await pushToQueue(
|
|
715
|
-
this.env.QUEUE_BUS_QUEUE,
|
|
716
|
-
eventsToEmit
|
|
717
|
-
);
|
|
718
|
-
}
|
|
719
705
|
return {
|
|
720
706
|
...lastSyncMetadata,
|
|
721
707
|
newLastSyncAt: effectiveWindow.dateTo
|
|
@@ -9,7 +9,6 @@ declare class BankProcessBatch extends WorkflowEntrypoint<BankEnv, Params$1> {
|
|
|
9
9
|
|
|
10
10
|
type Params = {
|
|
11
11
|
accountId: string;
|
|
12
|
-
maxIterations?: number;
|
|
13
12
|
};
|
|
14
13
|
declare class BankSyncAccountPayments extends WorkflowEntrypoint<BankEnv, Params> {
|
|
15
14
|
run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
|
|
@@ -9,7 +9,6 @@ declare class BankProcessBatch extends WorkflowEntrypoint<BankEnv, Params$1> {
|
|
|
9
9
|
|
|
10
10
|
type Params = {
|
|
11
11
|
accountId: string;
|
|
12
|
-
maxIterations?: number;
|
|
13
12
|
};
|
|
14
13
|
declare class BankSyncAccountPayments extends WorkflowEntrypoint<BankEnv, Params> {
|
|
15
14
|
run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
|
|
@@ -9,7 +9,6 @@ declare class BankProcessBatch extends WorkflowEntrypoint<BankEnv, Params$1> {
|
|
|
9
9
|
|
|
10
10
|
type Params = {
|
|
11
11
|
accountId: string;
|
|
12
|
-
maxIterations?: number;
|
|
13
12
|
};
|
|
14
13
|
declare class BankSyncAccountPayments extends WorkflowEntrypoint<BankEnv, Params> {
|
|
15
14
|
run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
|
|
@@ -2,7 +2,7 @@ import { first, uuidv4, asNonEmpty } from '@develit-io/backend-sdk';
|
|
|
2
2
|
import { G as tables, H as relations, v as toBatchedPaymentFromPaymentRequest, z as toPreparedPayment, m as isPaymentCompleted } from '../shared/bank.kz-PKVi5.mjs';
|
|
3
3
|
import { i as isBatchAuthorized, b as isBatchFailed, d as isBatchProcessing } from '../shared/bank.XqSw509X.mjs';
|
|
4
4
|
import { sql, and, eq, inArray } from 'drizzle-orm';
|
|
5
|
-
import { g as getBatchByIdQuery, a as getPaymentRequestsByBatchIdQuery, c as checksum, u as upsertBatchCommand, b as getAccountByIdQuery, d as createCredentialsResolver, i as initiateConnector, e as updatePaymentRequestStatusCommand, f as
|
|
5
|
+
import { g as getBatchByIdQuery, a as getPaymentRequestsByBatchIdQuery, c as checksum, u as upsertBatchCommand, b as getAccountByIdQuery, d as createCredentialsResolver, i as initiateConnector, e as updatePaymentRequestStatusCommand, f as createPaymentCommand } from '../shared/bank.BWR4dqQ5.mjs';
|
|
6
6
|
import { WorkflowEntrypoint } from 'cloudflare:workers';
|
|
7
7
|
import { NonRetryableError } from 'cloudflare:workflows';
|
|
8
8
|
import { drizzle } from 'drizzle-orm/d1';
|
|
@@ -423,8 +423,7 @@ async function pushToQueue(queue, message) {
|
|
|
423
423
|
}
|
|
424
424
|
class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
425
425
|
async run(event, step) {
|
|
426
|
-
const { accountId
|
|
427
|
-
const iterationBudget = resolveIterationBudget(maxIterations);
|
|
426
|
+
const { accountId } = event.payload;
|
|
428
427
|
const db = drizzle(this.env.BANK_D1, { schema: tables, relations });
|
|
429
428
|
const logger = createWorkflowLogger(event.instanceId);
|
|
430
429
|
if (!accountId) {
|
|
@@ -434,7 +433,7 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
|
434
433
|
"capture workflow start time",
|
|
435
434
|
async () => Date.now()
|
|
436
435
|
);
|
|
437
|
-
for (let iteration = 0;
|
|
436
|
+
for (let iteration = 0; ; iteration++) {
|
|
438
437
|
const account = await step.do("load account", async () => {
|
|
439
438
|
const account2 = await getAccountByIdQuery(db, { accountId });
|
|
440
439
|
if (!account2) {
|
|
@@ -453,19 +452,6 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
|
453
452
|
if (!account.lastSyncAt) {
|
|
454
453
|
throw new Error(`lastSyncedAt is not set for account: ${accountId}`);
|
|
455
454
|
}
|
|
456
|
-
if (isSupersededBy(
|
|
457
|
-
event.instanceId,
|
|
458
|
-
account.lastSyncMetadata?.instanceId,
|
|
459
|
-
accountId
|
|
460
|
-
)) {
|
|
461
|
-
logger.info("sync.superseded", {
|
|
462
|
-
accountId,
|
|
463
|
-
instanceId: event.instanceId,
|
|
464
|
-
supersededBy: account.lastSyncMetadata?.instanceId,
|
|
465
|
-
iteration
|
|
466
|
-
});
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
455
|
const lastSyncAtMs = account.lastSyncAt.getTime();
|
|
470
456
|
const windowMs = await step.do("resolve sync window", async () => {
|
|
471
457
|
const window = resolveSyncWindow(
|
|
@@ -693,6 +679,12 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
|
693
679
|
lastSyncMetadata,
|
|
694
680
|
seenInstanceId: account.lastSyncMetadata?.instanceId ?? null
|
|
695
681
|
}).command;
|
|
682
|
+
if (eventsToEmit.length) {
|
|
683
|
+
await pushToQueue(
|
|
684
|
+
this.env.QUEUE_BUS_QUEUE,
|
|
685
|
+
eventsToEmit
|
|
686
|
+
);
|
|
687
|
+
}
|
|
696
688
|
let syncStateRows;
|
|
697
689
|
if (createCommands.length) {
|
|
698
690
|
const [updateResult] = await db.batch(
|
|
@@ -708,12 +700,6 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
|
708
700
|
instanceId: event.instanceId
|
|
709
701
|
});
|
|
710
702
|
}
|
|
711
|
-
if (eventsToEmit.length) {
|
|
712
|
-
await pushToQueue(
|
|
713
|
-
this.env.QUEUE_BUS_QUEUE,
|
|
714
|
-
eventsToEmit
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
703
|
return {
|
|
718
704
|
...lastSyncMetadata,
|
|
719
705
|
newLastSyncAt: effectiveWindow.dateTo
|
package/dist/service.d.cts
CHANGED
|
@@ -17,9 +17,6 @@ interface BankServiceVariables {
|
|
|
17
17
|
DBUCS_TX_AUTH_URI: string;
|
|
18
18
|
REDIRECT_URI: string;
|
|
19
19
|
SYNC_WORKFLOW_RESET_AFTER_ITERATIONS: string;
|
|
20
|
-
CRON_SYNC_WORKFLOW_DISPATCH: string;
|
|
21
|
-
SYNC_DISPATCH_ACCOUNT_IDS: string;
|
|
22
|
-
SYNC_WORKFLOW_MAX_ITERATIONS: string;
|
|
23
20
|
[key: string]: string | number | boolean;
|
|
24
21
|
}
|
|
25
22
|
declare const BANK_SERVICE_BINDINGS: {
|
package/dist/service.d.mts
CHANGED
|
@@ -17,9 +17,6 @@ interface BankServiceVariables {
|
|
|
17
17
|
DBUCS_TX_AUTH_URI: string;
|
|
18
18
|
REDIRECT_URI: string;
|
|
19
19
|
SYNC_WORKFLOW_RESET_AFTER_ITERATIONS: string;
|
|
20
|
-
CRON_SYNC_WORKFLOW_DISPATCH: string;
|
|
21
|
-
SYNC_DISPATCH_ACCOUNT_IDS: string;
|
|
22
|
-
SYNC_WORKFLOW_MAX_ITERATIONS: string;
|
|
23
20
|
[key: string]: string | number | boolean;
|
|
24
21
|
}
|
|
25
22
|
declare const BANK_SERVICE_BINDINGS: {
|
package/dist/service.d.ts
CHANGED
|
@@ -17,9 +17,6 @@ interface BankServiceVariables {
|
|
|
17
17
|
DBUCS_TX_AUTH_URI: string;
|
|
18
18
|
REDIRECT_URI: string;
|
|
19
19
|
SYNC_WORKFLOW_RESET_AFTER_ITERATIONS: string;
|
|
20
|
-
CRON_SYNC_WORKFLOW_DISPATCH: string;
|
|
21
|
-
SYNC_DISPATCH_ACCOUNT_IDS: string;
|
|
22
|
-
SYNC_WORKFLOW_MAX_ITERATIONS: string;
|
|
23
20
|
[key: string]: string | number | boolean;
|
|
24
21
|
}
|
|
25
22
|
declare const BANK_SERVICE_BINDINGS: {
|
|
@@ -7,33 +7,6 @@ import 'jose';
|
|
|
7
7
|
import '@develit-io/general-codes';
|
|
8
8
|
import { createHash } from 'node:crypto';
|
|
9
9
|
|
|
10
|
-
function parseInstanceWindow(instanceId, accountId) {
|
|
11
|
-
const prefix = `${accountId}-`;
|
|
12
|
-
if (!instanceId.startsWith(prefix)) return -1;
|
|
13
|
-
const suffix = instanceId.slice(prefix.length);
|
|
14
|
-
if (!/^\d+$/.test(suffix)) return -1;
|
|
15
|
-
return Number(suffix);
|
|
16
|
-
}
|
|
17
|
-
function resolveCurrentSyncInstanceId(accountId, recordedInstanceId) {
|
|
18
|
-
return recordedInstanceId ?? accountId;
|
|
19
|
-
}
|
|
20
|
-
function isSupersededBy(myInstanceId, recordedInstanceId, accountId) {
|
|
21
|
-
if (recordedInstanceId == null) return false;
|
|
22
|
-
return parseInstanceWindow(recordedInstanceId, accountId) > parseInstanceWindow(myInstanceId, accountId);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function normalizeBudget(value) {
|
|
26
|
-
if (!Number.isFinite(value) || value < 1) return void 0;
|
|
27
|
-
return Math.floor(value);
|
|
28
|
-
}
|
|
29
|
-
function parseIterationBudgetParam(value) {
|
|
30
|
-
return normalizeBudget(Number(value?.trim() || Number.NaN));
|
|
31
|
-
}
|
|
32
|
-
function resolveIterationBudget(maxIterations) {
|
|
33
|
-
if (maxIterations == null) return Number.POSITIVE_INFINITY;
|
|
34
|
-
return normalizeBudget(maxIterations) ?? Number.POSITIVE_INFINITY;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
10
|
const createPaymentCommand = (db, { payment }) => {
|
|
38
11
|
return {
|
|
39
12
|
command: db.insert(tables.payment).values({
|
|
@@ -386,4 +359,4 @@ const initiateConnector = async ({
|
|
|
386
359
|
}
|
|
387
360
|
};
|
|
388
361
|
|
|
389
|
-
export { getPaymentRequestsByBatchIdQuery as a, getAccountByIdQuery as b, checksum as c, createCredentialsResolver as d, updatePaymentRequestStatusCommand as e,
|
|
362
|
+
export { getPaymentRequestsByBatchIdQuery as a, getAccountByIdQuery as b, checksum as c, createCredentialsResolver as d, updatePaymentRequestStatusCommand as e, createPaymentCommand as f, getBatchByIdQuery as g, encrypt as h, initiateConnector as i, importAesKey as j, upsertBatchCommand as u };
|
|
@@ -9,33 +9,6 @@ require('jose');
|
|
|
9
9
|
require('@develit-io/general-codes');
|
|
10
10
|
const node_crypto = require('node:crypto');
|
|
11
11
|
|
|
12
|
-
function parseInstanceWindow(instanceId, accountId) {
|
|
13
|
-
const prefix = `${accountId}-`;
|
|
14
|
-
if (!instanceId.startsWith(prefix)) return -1;
|
|
15
|
-
const suffix = instanceId.slice(prefix.length);
|
|
16
|
-
if (!/^\d+$/.test(suffix)) return -1;
|
|
17
|
-
return Number(suffix);
|
|
18
|
-
}
|
|
19
|
-
function resolveCurrentSyncInstanceId(accountId, recordedInstanceId) {
|
|
20
|
-
return recordedInstanceId ?? accountId;
|
|
21
|
-
}
|
|
22
|
-
function isSupersededBy(myInstanceId, recordedInstanceId, accountId) {
|
|
23
|
-
if (recordedInstanceId == null) return false;
|
|
24
|
-
return parseInstanceWindow(recordedInstanceId, accountId) > parseInstanceWindow(myInstanceId, accountId);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function normalizeBudget(value) {
|
|
28
|
-
if (!Number.isFinite(value) || value < 1) return void 0;
|
|
29
|
-
return Math.floor(value);
|
|
30
|
-
}
|
|
31
|
-
function parseIterationBudgetParam(value) {
|
|
32
|
-
return normalizeBudget(Number(value?.trim() || Number.NaN));
|
|
33
|
-
}
|
|
34
|
-
function resolveIterationBudget(maxIterations) {
|
|
35
|
-
if (maxIterations == null) return Number.POSITIVE_INFINITY;
|
|
36
|
-
return normalizeBudget(maxIterations) ?? Number.POSITIVE_INFINITY;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
12
|
const createPaymentCommand = (db, { payment }) => {
|
|
40
13
|
return {
|
|
41
14
|
command: db.insert(paymentDirection.tables.payment).values({
|
|
@@ -397,9 +370,5 @@ exports.getBatchByIdQuery = getBatchByIdQuery;
|
|
|
397
370
|
exports.getPaymentRequestsByBatchIdQuery = getPaymentRequestsByBatchIdQuery;
|
|
398
371
|
exports.importAesKey = importAesKey;
|
|
399
372
|
exports.initiateConnector = initiateConnector;
|
|
400
|
-
exports.isSupersededBy = isSupersededBy;
|
|
401
|
-
exports.parseIterationBudgetParam = parseIterationBudgetParam;
|
|
402
|
-
exports.resolveCurrentSyncInstanceId = resolveCurrentSyncInstanceId;
|
|
403
|
-
exports.resolveIterationBudget = resolveIterationBudget;
|
|
404
373
|
exports.updatePaymentRequestStatusCommand = updatePaymentRequestStatusCommand;
|
|
405
374
|
exports.upsertBatchCommand = upsertBatchCommand;
|