toga-ai 1.0.760 → 1.0.761
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.
|
@@ -202,6 +202,43 @@ Prudential-EDI, S&P Global**.
|
|
|
202
202
|
- **Lesson:** any `sync*FromNetsuite()` that takes the record `&$byReference` and refetches must have
|
|
203
203
|
its fetch-by-id shim carry **every** field the caller reads afterward — `lastModifiedDate` first.
|
|
204
204
|
|
|
205
|
+
### ⚠ …but the by-reference shim wrote the cursor on the WRONG CLOCK → ITEM_RECEIPTS + ITEM_FULFILLMENTS re-matched forever (found + fixed 2026-09-03, NYCHH prod)
|
|
206
|
+
|
|
207
|
+
A follow-on to the by-reference fix directly above. Once the two shims carried a `lastModifiedDate`
|
|
208
|
+
again, the sections still could **not advance** — the value was in the **wrong timezone**, so
|
|
209
|
+
`lastmodifieddate > cursor` re-matched the **same record every run** (an infinite loop, no crash).
|
|
210
|
+
|
|
211
|
+
- **Root cause — two clocks.** The prior fix set `fetchItemFulfillmentById` / `fetchItemReceiptById`'s
|
|
212
|
+
`->lastModifiedDate` from the **REST record GET**, which returns **UTC** (e.g. `2024-08-06T14:45:00Z`).
|
|
213
|
+
`common_sync_togasupply.php` then `date()`-formats it in the script timezone **America/Chicago** →
|
|
214
|
+
`2024-08-06 09:45:00`, and stores that as the cursor. But the LIST fetch's `WHERE`
|
|
215
|
+
(`App_Api_Netsuite_Rest::listItem*`) compares `lastmodifieddate` via SuiteQL
|
|
216
|
+
`TO_CHAR(lastmodifieddate,'YYYY-MM-DD HH24:MI:SS')`, which is the **NetSuite account timezone =
|
|
217
|
+
Eastern** → `2024-08-06 10:45:16`. So the cursor was written **~1 hour behind** the clock the fetch
|
|
218
|
+
reads → `lastmodifieddate > cursor` was always still true for the record just processed → it was
|
|
219
|
+
re-fetched and re-processed forever and the watermark never moved.
|
|
220
|
+
- **Proven on NYCHH prod** (item receipt internalId `4953915`): REST GET `lastModifiedDate`
|
|
221
|
+
`2024-08-06T14:45:00Z` (UTC) · SuiteQL `2024-08-06 10:45:16` (Eastern) · stored cursor
|
|
222
|
+
`2024-08-06 09:45:00` (Chicago). ITEM_RECEIPTS was jammed on it; because that heavy receipt (nested
|
|
223
|
+
PO→SO reconcile) runs **before** fulfillments and starved the run, ITEM_FULFILLMENTS' window kept
|
|
224
|
+
collapsing to 6s and never grew to clear the empty gap to its first real record (2025-01-06; 1,294
|
|
225
|
+
NYCHH fulfillments waited after 2025-01-01).
|
|
226
|
+
- **INVENTORY_ADJUSTMENTS was NOT stuck** — `fetchInventoryAdjustmentById` already reads
|
|
227
|
+
`lastmodifieddate` from SuiteQL `TO_CHAR` (the right clock), so it advanced normally. **That is the
|
|
228
|
+
correct pattern**; the other two shims did not follow it.
|
|
229
|
+
- **Fix (library only, `php -l` clean, fail-loud preserved):** in `library/app/api/netsuite/rest.php`,
|
|
230
|
+
`fetchItemFulfillmentById` (~L2093) and `fetchItemReceiptById` (~L2254) now set
|
|
231
|
+
`$shim->lastModifiedDate` from a SuiteQL
|
|
232
|
+
`SELECT TO_CHAR(lastmodifieddate,'YYYY-MM-DD HH24:MI:SS') AS lastmodifieddate FROM transaction WHERE id = $id`
|
|
233
|
+
(Eastern) — matching `fetchInventoryAdjustmentById` — **instead of** the REST header's UTC
|
|
234
|
+
`$header->lastModifiedDate`. No shim reads the REST/UTC `lastModifiedDate` anymore. No worker change,
|
|
235
|
+
no SQL. After deploy the two sections resume and backfill on their own (idempotent).
|
|
236
|
+
- **Lesson:** the per-record cursor value MUST be written in the **same timezone the fetch `WHERE`
|
|
237
|
+
compares against** — SuiteQL account time (Eastern), never the REST record GET's UTC
|
|
238
|
+
`lastModifiedDate`. A cursor even an hour behind the fetch clock re-matches the same record forever.
|
|
239
|
+
This is the same SuiteQL-vs-REST clock trap as the date-only-format bug above — see the
|
|
240
|
+
[SuiteQL/REST shim doc](../../library/features/netsuite-suiteql-rest-shim.md).
|
|
241
|
+
|
|
205
242
|
### ⚠ Per-record isolation is SECTION-SPECIFIC — and SALES_ORDERS has NONE (corrected 2026-08-17)
|
|
206
243
|
|
|
207
244
|
Whether a bad record is "stepped over" or freezes the section depends entirely on whether **that
|
|
@@ -1175,6 +1212,15 @@ the code deploy).
|
|
|
1175
1212
|
|
|
1176
1213
|
## Change history
|
|
1177
1214
|
|
|
1215
|
+
- 2026-09-03 — **By-reference shim wrote the cursor on the WRONG CLOCK → ITEM_RECEIPTS + ITEM_FULFILLMENTS
|
|
1216
|
+
re-matched the same record forever (fixed, `library` only).** Follow-on to the same-day by-reference
|
|
1217
|
+
fix below: the shims set `lastModifiedDate` from the REST GET (UTC), `date()`-formatted in
|
|
1218
|
+
America/Chicago, but the LIST `WHERE` compares SuiteQL `TO_CHAR(lastmodifieddate)` in the NetSuite
|
|
1219
|
+
account tz (Eastern), so the cursor sat ~1h behind the fetch clock and `lastmodifieddate > cursor`
|
|
1220
|
+
always re-matched — infinite loop, no crash. `fetchItemFulfillmentById`/`fetchItemReceiptById`
|
|
1221
|
+
(`rest.php` ~L2093/~L2254) now read `lastmodifieddate` from SuiteQL `TO_CHAR` (Eastern), matching
|
|
1222
|
+
`fetchInventoryAdjustmentById` (already correct). Proven on NYCHH prod (item receipt 4953915). No
|
|
1223
|
+
worker/SQL change; sections self-backfill after deploy. (jcardinal)
|
|
1178
1224
|
- 2026-09-03 — **By-reference refetch dropped `lastModifiedDate` → ITEM_FULFILLMENTS + INVENTORY_ADJUSTMENTS
|
|
1179
1225
|
froze (fixed, `library` only).** GroWrk's ITEM_FULFILLMENTS was re-throwing every 5 min since the
|
|
1180
1226
|
2026-09-02 per-record cursor deploy (`Undefined property: stdClass::$lastModifiedDate` at
|
package/package.json
CHANGED