toga-ai 1.0.751 → 1.0.752
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.
|
@@ -104,18 +104,22 @@ that worker job does the syncing, this library class notices when it stops.
|
|
|
104
104
|
checkpoints mean anything; and a client that is held / never transacts supply (AIG) must be
|
|
105
105
|
left **off** this list or it produces permanent false-positive tickets.
|
|
106
106
|
|
|
107
|
-
- **⚠
|
|
108
|
-
|
|
109
|
-
`NETSUITE_LAST_SYNC_DATETIME_<SECTION>` to
|
|
110
|
-
`"<lastmodifieddate>|<netsuite id>"`). This monitor's
|
|
111
|
-
`DATETIME` keys, so
|
|
112
|
-
reports OK forever — no stale-checkpoint alerts
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
- **⚠ THIS MONITOR IS NOW BLIND — the cursor-rename shipped 2026-09-02 and this monitor was NOT updated.**
|
|
108
|
+
The sync's per-record resume cursor deployed to prod 2026-09-02 (worker `06e8f9ef` + library `3a70b59c`),
|
|
109
|
+
renaming each section's position key from `NETSUITE_LAST_SYNC_DATETIME_<SECTION>` to
|
|
110
|
+
`NETSUITE_LAST_SYNC_CURSOR_<SECTION>` (value now `"<lastmodifieddate>|<netsuite id>"`). This monitor's
|
|
111
|
+
`NETSUITE_SYNC_PARAMETER_KEYS` still lists the old `DATETIME` keys, so its `where..in` `/parameters` read
|
|
112
|
+
now matches **zero rows** and it reports OK forever — **no stale-checkpoint alerts fire**. This was an
|
|
113
|
+
accepted gap at deploy time, but it is now live. **FIX OWED:** update `NETSUITE_SYNC_PARAMETER_KEYS` to the
|
|
114
|
+
`CURSOR` names **and** parse the `<date>|<id>` value (`strtotime` the part before `|`) before the 48h
|
|
115
|
+
compare. See the [per-client sync doc](../../worker/features/netsuite-togasupply-per-client-sync.md).
|
|
116
116
|
|
|
117
117
|
## Change history
|
|
118
118
|
|
|
119
|
+
- 2026-09-02 — **The sync's `NETSUITE_LAST_SYNC_DATETIME_*` → `NETSUITE_LAST_SYNC_CURSOR_*` rename SHIPPED to
|
|
120
|
+
prod (worker `06e8f9ef` + library `3a70b59c`), so this monitor is now BLIND** — its `where..in` read matches
|
|
121
|
+
zero rows and it reports OK forever. Monitor was not updated with the rename (accepted gap, now live). Fix
|
|
122
|
+
owed: update `NETSUITE_SYNC_PARAMETER_KEYS` to the CURSOR names + `strtotime` the part before `|`. (jcardinal)
|
|
119
123
|
- 2026-09-02 — Flagged that the sync's pending `NETSUITE_LAST_SYNC_DATETIME_*` →
|
|
120
124
|
`NETSUITE_LAST_SYNC_CURSOR_*` key rename (BUILT, not yet deployed) will make this monitor match zero rows
|
|
121
125
|
and stop alerting; it was intentionally left un-updated. Update the key list + parse the `<date>|<id>`
|
|
@@ -92,12 +92,14 @@ its IDLE write. **There is no timeout, memory cap, or resource limit anywhere in
|
|
|
92
92
|
never *tune the window size down*. (Corollary: a window that has grown back to the cap is positive
|
|
93
93
|
evidence the section is completing.)
|
|
94
94
|
|
|
95
|
-
### Per-record resume cursor — checkpoint after EACH record, not window-end (
|
|
95
|
+
### Per-record resume cursor — checkpoint after EACH record, not window-end (LIVE 2026-09-02)
|
|
96
96
|
|
|
97
97
|
The historical weakness of window-end-only checkpointing: a mid-window crash (poison record, or the
|
|
98
98
|
log-DB doom loop above) re-processes the **whole** window every run — the giant-fulfillment doom loop is a
|
|
99
99
|
direct consequence. This change converts the checkpoint to **per-record keyset (seek) resume** so a
|
|
100
|
-
transient crash resumes at the next record instead of redoing the window.
|
|
100
|
+
transient crash resumes at the next record instead of redoing the window. **Deployed to prod
|
|
101
|
+
2026-09-02** — worker commit `06e8f9ef` + library commit `3a70b59c` (both tips of `_production`), with the
|
|
102
|
+
rename migration run on every client DB first (see the deploy-order gotcha below).
|
|
101
103
|
|
|
102
104
|
- **Key rename per section:** `NETSUITE_LAST_SYNC_DATETIME_<SECTION>` → `NETSUITE_LAST_SYNC_CURSOR_<SECTION>`,
|
|
103
105
|
value format **`"<lastmodifieddate>|<netsuite internal id>"`**. The id breaks same-second ties.
|
|
@@ -109,10 +111,16 @@ transient crash resumes at the next record instead of redoing the window.
|
|
|
109
111
|
already carried it).
|
|
110
112
|
- **Save after EACH main record** (one PUT of `lastmod|id`); on a clean window with 0 records, PUT
|
|
111
113
|
`"<windowTop>|0"` so empty date ranges still advance. No new `try/catch` — stays fail-loud.
|
|
112
|
-
- **Migration is MANDATORY
|
|
114
|
+
- **Migration is MANDATORY, and runs BEFORE the code (see the deploy-order gotcha in Gotchas):**
|
|
113
115
|
`dbchanges2/Client/2026-09-02b - NetsuiteSyncCursorRename.sql` (Client fan-out) renames the keys **and**
|
|
114
|
-
appends `|0` to carry the value across; safe to re-run.
|
|
115
|
-
|
|
116
|
+
appends `|0` to carry the value across; safe to re-run. It was run on all client DBs first, then the
|
|
117
|
+
code deployed — the required order.
|
|
118
|
+
- **⚠ OPEN follow-up — new-client seed was edited in place (dbchanges2 rule violation).** The seed module
|
|
119
|
+
`dbchanges2/_modules/netsuite/2026-08-05 - CLEAN NETSUITE CLINET.SQL` had its 6 seed rows **renamed in
|
|
120
|
+
place** to CURSOR keys with `|0`. That breaks the dbchanges2 "never edit an already-applied file" rule and
|
|
121
|
+
the client-schema drift audit. **Revert that file and add a NEW dated `_modules/netsuite/` file** carrying
|
|
122
|
+
the same guarded `UPDATE ... WHERE key LIKE 'NETSUITE_LAST_SYNC_DATETIME_%'` so future new clients land on
|
|
123
|
+
CURSOR keys. Still uncommitted in the working tree.
|
|
116
124
|
|
|
117
125
|
### ⚠ Per-record isolation is SECTION-SPECIFIC — and SALES_ORDERS has NONE (corrected 2026-08-17)
|
|
118
126
|
|
|
@@ -330,9 +338,11 @@ Per-client `Parameters` table (2.0 client DB, e.g. `Client_Canon.Parameters`; co
|
|
|
330
338
|
|
|
331
339
|
Parameters are stored **per client DB** but accessed **through the TOGa2 API**, not direct SQL.
|
|
332
340
|
|
|
333
|
-
**
|
|
334
|
-
`NETSUITE_LAST_SYNC_CURSOR_<SECTION>` with value `"<lastmodifieddate>|<netsuite internal id>"`
|
|
335
|
-
per-record resume cursor in *How it works*. The `NETSUITE_EXECUTION_MODE_*` keys are
|
|
341
|
+
**Key rename (LIVE 2026-09-02):** the position keys are now
|
|
342
|
+
`NETSUITE_LAST_SYNC_CURSOR_<SECTION>` with value `"<lastmodifieddate>|<netsuite internal id>"` for all 6
|
|
343
|
+
sections — see the per-record resume cursor in *How it works*. The `NETSUITE_EXECUTION_MODE_*` keys are
|
|
344
|
+
unchanged. Renamed on every client DB by `Client/2026-09-02b - NetsuiteSyncCursorRename.sql` (run before
|
|
345
|
+
the code deploy).
|
|
336
346
|
|
|
337
347
|
## Client variations
|
|
338
348
|
|
|
@@ -488,6 +498,19 @@ per-record resume cursor in *How it works*. The `NETSUITE_EXECUTION_MODE_*` keys
|
|
|
488
498
|
`$dateField='lastmodifieddate'` and the engine calls it without the 4th arg. So a backdated
|
|
489
499
|
`trandate` is irrelevant to whether an invoice imports, and a just-modified invoice still won't
|
|
490
500
|
import until it is >24h old (the upper-bound cap).
|
|
501
|
+
- **⚠ DEPLOY ORDER: the cursor-rename migration MUST run on EVERY client DB before the worker/library
|
|
502
|
+
deploy — there is NO old-key fallback in code.** `Client/2026-09-02b - NetsuiteSyncCursorRename.sql`
|
|
503
|
+
renames `NETSUITE_LAST_SYNC_DATETIME_<SECTION>` → `NETSUITE_LAST_SYNC_CURSOR_<SECTION>`. If the code
|
|
504
|
+
ships first, `startModeIteration()` reads a CURSOR key that doesn't exist yet and falls back to
|
|
505
|
+
`MIN_DATETIME_TO_CHECK_FOR_NETSUITE_DATA` (= `'2018-01-01'` for 17 of 18 clients) — re-scanning ~8 years
|
|
506
|
+
across all sections and all clients at once, a thundering herd against NetSuite + api2. Both the php and
|
|
507
|
+
sql reviewers flagged this as critical. The 2026-09-02 deploy followed the correct order (migration on all
|
|
508
|
+
client DBs first, then code). Same rule for any future position-key rename: schema first, code second.
|
|
509
|
+
- **Per-record checkpoint PUT multiplies api2 round-trips on high-count catch-up windows (tuning note, not
|
|
510
|
+
shipped).** The per-record resume cursor does one `App_Api_Toga2::send` PUT per record. On a big backfill
|
|
511
|
+
window (e.g. sales orders / POs) that is one extra api2 round-trip per record. Optional future tuning:
|
|
512
|
+
batch the checkpoint every N records while still writing it **before** the next record's dispatch (so
|
|
513
|
+
crash-resume stays correct). Not built.
|
|
491
514
|
- **A parse error in the shared `library/app/api/netsuite/rest.php` takes down EVERY client at
|
|
492
515
|
once (tier-wide outage).** All wrappers autoload `App_Api_Netsuite_Rest` in the pre-section
|
|
493
516
|
LOOKUPS/setup phase of `common_sync_togasupply.php` (~line 433). Because PHP parses the whole
|
|
@@ -1044,8 +1067,16 @@ per-record resume cursor in *How it works*. The `NETSUITE_EXECUTION_MODE_*` keys
|
|
|
1044
1067
|
|
|
1045
1068
|
## Change history
|
|
1046
1069
|
|
|
1047
|
-
- 2026-09-02 — **Per-record resume cursor
|
|
1048
|
-
|
|
1070
|
+
- 2026-09-02 — **Per-record resume cursor DEPLOYED to prod (shared: `worker` + `library` + `dbchanges2`).**
|
|
1071
|
+
Now live: worker commit `06e8f9ef` + library commit `3a70b59c` (tips of `_production`); rename migration
|
|
1072
|
+
`Client/2026-09-02b - NetsuiteSyncCursorRename.sql` run on all client DBs **before** the code. Recorded the
|
|
1073
|
+
deploy-order rule (no old-key fallback — code-first would fall back to `MIN_DATETIME_TO_CHECK_FOR_NETSUITE_DATA`
|
|
1074
|
+
= `'2018-01-01'` and thundering-herd re-scan ~8 years for all clients; php + sql reviewers flagged it
|
|
1075
|
+
critical). Two open items: (1) the new-client seed `_modules/netsuite/2026-08-05 - CLEAN NETSUITE CLINET.SQL`
|
|
1076
|
+
was edited in place (dbchanges2 rule violation) — revert + add a new dated file; (2) optional tuning — batch
|
|
1077
|
+
the per-record checkpoint PUT every N records on high-count windows. Both still uncommitted. (jcardinal)
|
|
1078
|
+
- 2026-09-02 — **Per-record resume cursor BUILT (shared: `worker` + `library` + `dbchanges2`; shipped later
|
|
1079
|
+
the same day — see entry above).** Converts the section checkpoint from window-end-only to per-record
|
|
1049
1080
|
keyset resume so a mid-window crash (poison record or the log-DB doom loop) resumes at the next record
|
|
1050
1081
|
instead of re-processing the whole window. Position key `NETSUITE_LAST_SYNC_DATETIME_<SECTION>` →
|
|
1051
1082
|
`NETSUITE_LAST_SYNC_CURSOR_<SECTION>`, value `"<lastmodifieddate>|<netsuite id>"` (id breaks same-second
|
package/package.json
CHANGED