toga-ai 1.0.142 → 1.0.144
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.
|
@@ -58,12 +58,12 @@ App_Api_Netsuite_Rest::authenticate(); // acquire OAuth2 token once
|
|
|
58
58
|
- In our usage the client is effectively **read-only**: only `GET` (record fetch) and `POST`
|
|
59
59
|
(SuiteQL) are exercised. `send()` accepts any verb (incl. PATCH/PUT) but we don't write through it.
|
|
60
60
|
|
|
61
|
-
###
|
|
61
|
+
### Disabling logging for ad-hoc SuiteQL probes
|
|
62
62
|
|
|
63
|
-
`App_Api_Netsuite_Rest::send()` auto-authenticates
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
`App_Api_Netsuite_Rest::send()` auto-authenticates and logs to the API-log DB by default (it does
|
|
64
|
+
**not** call `setLogging(false)`). That's fine in normal environments; for a one-off **read-only
|
|
65
|
+
probe** you can keep the call out of the API log by authenticating once and issuing your own
|
|
66
|
+
`App_ApiTransaction` with logging off:
|
|
67
67
|
|
|
68
68
|
```php
|
|
69
69
|
$url = rtrim(App_Api_Netsuite_Rest::$endpoint, '/') . App_Api_Netsuite_Rest::API_BASE_PATH
|
package/knowledge/1.0/apps/worker/workflows/onboarding-client-to-netsuite-togasupply-sync.md
CHANGED
|
@@ -90,7 +90,7 @@ the directory; no `USE`).
|
|
|
90
90
|
with "Unknown database 'logs_<name>'" if absent.
|
|
91
91
|
- Run the cron in place with `C:\xampp8\php\php.exe` from the `worker/` dir; the autoloader
|
|
92
92
|
walks up to `worker/_` for `__APPROOT__`. `App_Api_Netsuite_Rest::authenticate()` +
|
|
93
|
-
`App_ApiTransaction->setLogging(false)` is the
|
|
93
|
+
`App_ApiTransaction->setLogging(false)` is the read-only SuiteQL probe pattern (see
|
|
94
94
|
`test/@dave/nsq.php`, a read-only SuiteQL runner).
|
|
95
95
|
- Verified behavior: empty window → 0 writes, checkpoint advances (clean no-op); record
|
|
96
96
|
already present → `PUT` update (idempotent, keyed on `c_netsuiteInternalSalesOrderId`, no
|
|
@@ -145,8 +145,8 @@ Shared helpers: `buildCustomFields()` (the field array, used by both create and
|
|
|
145
145
|
`Presales Lead Email`, and `Presales Lead` (users field).
|
|
146
146
|
- The ClickUp token comes from `[clickup] token` in the worker2 config (legacy webhook received
|
|
147
147
|
it on the payload; the new contract drops it).
|
|
148
|
-
- Every ClickUp `_ApiRequest` calls `setLogging(self::CLICKUP_API_LOGGING_ENABLED=false)
|
|
149
|
-
|
|
148
|
+
- Every ClickUp `_ApiRequest` calls `setLogging(self::CLICKUP_API_LOGGING_ENABLED=false)`, so ClickUp
|
|
149
|
+
traffic is not written to the Logs DB.
|
|
150
150
|
|
|
151
151
|
## Data model
|
|
152
152
|
|
|
@@ -181,6 +181,35 @@ None — platform-wide Forecast sync.
|
|
|
181
181
|
at all. Give `ss_amq_drain` a dedicated `Not Scheduled` deployment as the on-demand slot (add more
|
|
182
182
|
for concurrency) and keep a `Scheduled` one for the cron. Submit by **scriptId only** — the
|
|
183
183
|
deployment id is prefix-doubled (`customdeploycustomdeploy_ss_amq_drain`).
|
|
184
|
+
- **Under a create/edit burst the on-demand kick still drops with `NO_DEPLOYMENTS_AVAILABLE`, and the
|
|
185
|
+
scheduled drainer is the ONLY backstop — but its floor is 15 min, which is NOT acceptable as the normal
|
|
186
|
+
path.** When the automated process mass-creates records, enqueues outrun the `Not Scheduled` slot pool;
|
|
187
|
+
the enqueuer logs `AMQ drainer NOT kicked (cron will catch it)` and the row sits `Created` until the cron
|
|
188
|
+
sweeps it. Widening the slot pool (we run **1 Scheduled + ≥4 Not Scheduled** `ss_amq_drain` deployments)
|
|
189
|
+
raises the ceiling; `Created` is sweepable so a dropped kick is a *delay*, not a loss (only terminal
|
|
190
|
+
`Failed`, after `maxRetries`, is a true dead-letter). **But the push must stay near-real-time via the
|
|
191
|
+
kick — do not "fix" the read-races by deferring delivery to the cron.** And you **cannot add a settle
|
|
192
|
+
delay inside the SuiteScript**: server-side SuiteScript has **no `sleep()` and no `setTimeout`** (no event
|
|
193
|
+
loop); a `while(Date.now()<t){}` busy-wait would block the UE `afterSubmit` (the user's save) and trip the
|
|
194
|
+
execution-time limit. Any "let the record settle before reading" mitigation belongs on the **worker2 read
|
|
195
|
+
side** (PHP can sleep), never the enqueuer. (See the open-orders doc's REST-sublist read-after-write-lag
|
|
196
|
+
gotcha for why a settle/SuiteQL-source fix is wanted in the first place.)
|
|
197
|
+
- **A `Released` UE deployment with an EMPTY audience fires for NO ONE — `Released` ≠ active.** Live
|
|
198
|
+
incident 2026-06-18: the Opportunity `ue_amq_enqueue` deployment was flipped `Testing → Released` at
|
|
199
|
+
~4:41 pm but **Audience: All Roles / All Employees were still F**, so it enqueued nothing for ~1 h until
|
|
200
|
+
the audience was set to T at ~5:39 pm. Result: a batch of opportunities created in that window never
|
|
201
|
+
enqueued (no queue row, no worker2 job) and silently missed the Forecast import — diagnosed by the
|
|
202
|
+
enqueuer's `scriptnote` AUDIT log going quiet and the missing opps having zero log entries. When opps go
|
|
203
|
+
missing, **check the enqueuer deployment's Status AND Audience (All Roles/All Employees = T)**, not just
|
|
204
|
+
"is it Released." Backfill the gap window with `trueup_opportunities.php`.
|
|
205
|
+
- **NetSuite SuiteQL renders timestamps in TWO different zones — do not compare them naïvely.** Stored
|
|
206
|
+
datetime fields (a custom record's `created`, transaction dates, `systemnote.date`) and the NetSuite UI
|
|
207
|
+
render in the **account/user TZ (Eastern here)**, but **`SYSDATE` and `scriptnote.date` render in
|
|
208
|
+
server/Pacific (UTC−7)**. Meanwhile webhook payload timestamps are UTC (`...Z`) and `WorkerJobs` is CDT
|
|
209
|
+
(UTC−5). Mixing these silently produces hours-off conclusions (it sent us down a wrong "out-of-order /
|
|
210
|
+
empty-record" path for a while). Anchor every comparison to UTC, and verify the zone of each source with a
|
|
211
|
+
known same-event cross-reference (e.g. a `scriptnote` AUDIT entry's internalId ↔ that event's UTC webhook
|
|
212
|
+
payload ↔ its `WorkerJobs.dtCreated`) before trusting a delta.
|
|
184
213
|
- **worker2 routes EVERY request to `_Controller_Index::worker()`** — `worker2/_.php` sets
|
|
185
214
|
`DEFAULT_CONTROLLER_METHOD = ['_Controller_Index','worker']`, which short-circuits `_Route`'s
|
|
186
215
|
URI matching. There is no per-URL routing, and `.htaccess` denies direct `.php` files, so you
|
|
@@ -277,6 +306,14 @@ same **skip-if-unchanged** compare on the extracted values, and **actor-identity
|
|
|
277
306
|
trigger a CU→NS write. The NS→CU change-detection above is the complementary backstop, not a substitute.
|
|
278
307
|
|
|
279
308
|
## Change history
|
|
309
|
+
- 2026-06-18 — **Diagnosed the live opportunity-import gap as a deployment misconfig + characterized the
|
|
310
|
+
AMQ burst behavior.** The Opportunity `ue_amq_enqueue` deployment was `Released` but with an **empty
|
|
311
|
+
audience** (~4:41–5:39 pm) so it enqueued nothing; missing opps had no queue row and no worker2 job
|
|
312
|
+
(enqueuer `scriptnote` log went silent). Also recorded: under bursts the on-demand kick drops with
|
|
313
|
+
`NO_DEPLOYMENTS_AVAILABLE` (widened to 1 Scheduled + ≥4 Not Scheduled `ss_amq_drain` slots; cron is the
|
|
314
|
+
redundancy backstop but its 15-min floor is not an acceptable normal path); **SuiteScript has no
|
|
315
|
+
`sleep`/`setTimeout`** so settle delays must live on the worker2 read side; and the **SuiteQL mixed-TZ
|
|
316
|
+
rendering** trap (stored fields = account/Eastern; `SYSDATE`/`scriptnote` = server/Pacific). (dfranks)
|
|
280
317
|
- 2026-06-18 — **Verified live in production** (no code change): real NetSuite SuiteScript webhooks
|
|
281
318
|
(`user-agent: NetSuite/2026.1`) arrive at `webhook.togahub.com/netsuite` and process successfully
|
|
282
319
|
(e.g. opp 6926224 PUT). Clarified that **`UPDATE_CLICKUP = false` is an intentional one-way guard**
|
package/package.json
CHANGED