toga-ai 1.0.144 → 1.0.145
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.
|
@@ -6,8 +6,8 @@ project: Worker
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-06-
|
|
10
|
-
owners: [jcardinal]
|
|
9
|
+
updated: 2026-06-18
|
|
10
|
+
owners: [jcardinal, dfranks]
|
|
11
11
|
files:
|
|
12
12
|
- worker2/Worker/
|
|
13
13
|
- worker2/Controller/Index.php
|
|
@@ -126,6 +126,31 @@ curl -X POST https://worker.togahub.com/ \
|
|
|
126
126
|
|
|
127
127
|
Use realistic placeholder values, not empty strings/nulls.
|
|
128
128
|
|
|
129
|
+
## How exceptions & retries work
|
|
130
|
+
|
|
131
|
+
The EB worker dispatcher (`Controller/Index.php::worker()`) wraps your action call in
|
|
132
|
+
`try { } catch (\Throwable $e)`:
|
|
133
|
+
- **Returns normally** → `WorkerJobs.isSuccess = 1`, `dtCompleted` set.
|
|
134
|
+
- **Throws** (any `Throwable`, incl. `Error`) → `isSuccess = 0`, `failureReason` = message +
|
|
135
|
+
`file:line` + full stack trace. (Two earlier phases — DB-logs registration and `initialize()` —
|
|
136
|
+
fail the same way.)
|
|
137
|
+
|
|
138
|
+
Crucially, the worker **always returns HTTP 200, even on a throw**, so SQS deletes the message
|
|
139
|
+
immediately. **There is no DLQ and no automatic retry.** A throw makes the failure *visible* (a
|
|
140
|
+
failed `WorkerJobs` row to alert on) — it does **not** re-run the job.
|
|
141
|
+
|
|
142
|
+
So **do not design "throw so it retries" — it won't.** To actually retry / self-heal:
|
|
143
|
+
- **Re-enqueue** with `_Worker::runTask('Category/Action/Method', [...])` — inserts a fresh
|
|
144
|
+
`WorkerJobs` row + SQS message, so it genuinely re-runs. Carry your own **attempt counter** in the
|
|
145
|
+
parameters to bound it.
|
|
146
|
+
- Or **in-process retry** *within* the method (it's a background worker with a 3600s visibility
|
|
147
|
+
budget — a bounded sleep+retry loop is fine here, unlike a request handler).
|
|
148
|
+
- Or **manual** `_Worker_Infrastructure_Worker::Retry($id)` / the reset-fields SQL, or a periodic
|
|
149
|
+
reconcile cron as a backstop.
|
|
150
|
+
|
|
151
|
+
Rule of thumb: `throw` to surface a genuine failure; `runTask`/in-process loop when the work should
|
|
152
|
+
be reattempted.
|
|
153
|
+
|
|
129
154
|
## Gotchas
|
|
130
155
|
|
|
131
156
|
- Class must be **`abstract`** and methods **`public static`** or routing fails.
|
|
@@ -135,4 +160,8 @@ Use realistic placeholder values, not empty strings/nulls.
|
|
|
135
160
|
commit-before-SQS transaction pattern that the worker relies on.
|
|
136
161
|
|
|
137
162
|
## Change history
|
|
163
|
+
- 2026-06-18 — Documented worker-action **exception/retry semantics**: dispatcher catches `Throwable` →
|
|
164
|
+
`isSuccess=0`+`failureReason`, **always HTTP 200, no DLQ, no auto-retry**; throwing surfaces a failure
|
|
165
|
+
but does not re-run — retry via `_Worker::runTask` re-enqueue (attempt-counter), in-process loop, or
|
|
166
|
+
manual `Retry()`. (dfranks)
|
|
138
167
|
- 2026-06-08 — Documented the worker-action contract (path→class/method convention, parameter typing, webhook/cron templates); replaces the former `/worker2-action` skill. (jcardinal)
|
|
@@ -147,6 +147,17 @@ Shared helpers: `buildCustomFields()` (the field array, used by both create and
|
|
|
147
147
|
it on the payload; the new contract drops it).
|
|
148
148
|
- Every ClickUp `_ApiRequest` calls `setLogging(self::CLICKUP_API_LOGGING_ENABLED=false)`, so ClickUp
|
|
149
149
|
traffic is not written to the Logs DB.
|
|
150
|
+
- **Two `_Component_Api_Netsuite` classes exist — edit the right one.** worker2 calls the **global**
|
|
151
|
+
`_Component_Api_Netsuite`, autoloaded from `_underscore/Component/Api/Netsuite/Netsuite.php`; `api2`
|
|
152
|
+
ships a *separate* `namespace api` copy (`\api\_Component_Api_Netsuite`) for its own use. Editing the
|
|
153
|
+
api2 copy has **no effect** on the worker2 webhook integration — change the `_underscore` one.
|
|
154
|
+
- **NetSuite REST calls are NOT logged to `Logs.Api`.** `_Component_Api_Netsuite::send()` calls
|
|
155
|
+
`setLogging(false)`, so unlike platform traffic and ClickUp/Freshservice/Sentry (which land in the
|
|
156
|
+
logs-cluster `Logs.Api` with full request + `responsePayload`), NetSuite request/response bodies are
|
|
157
|
+
not captured — you can't pull a historical NetSuite response for debugging. That cost us the response
|
|
158
|
+
bodies when diagnosing the [open-orders read-after-write lag](./netsuite-salesorder-open-orders-sync.md);
|
|
159
|
+
removing that `setLogging(false)` is under review (handle the 20–50 KB payload volume the
|
|
160
|
+
prod-appropriate way — retention/sampling/summary — not by defaulting logging off).
|
|
150
161
|
|
|
151
162
|
## Data model
|
|
152
163
|
|
|
@@ -306,6 +317,11 @@ same **skip-if-unchanged** compare on the extracted values, and **actor-identity
|
|
|
306
317
|
trigger a CU→NS write. The NS→CU change-detection above is the complementary backstop, not a substitute.
|
|
307
318
|
|
|
308
319
|
## Change history
|
|
320
|
+
- 2026-06-18 — Documented two NetSuite-client gotchas: **two `_Component_Api_Netsuite` copies** (worker2
|
|
321
|
+
uses the global `_underscore` one; api2 has a separate `namespace api` copy — edit the right one), and
|
|
322
|
+
`send()`'s `setLogging(false)` means **NetSuite calls aren't logged to `Logs.Api`** (no historical
|
|
323
|
+
response bodies; removal under review). Also dropped the debunked dev-laptop rationale from the
|
|
324
|
+
ClickUp-logging note. (dfranks)
|
|
309
325
|
- 2026-06-18 — **Diagnosed the live opportunity-import gap as a deployment misconfig + characterized the
|
|
310
326
|
AMQ burst behavior.** The Opportunity `ue_amq_enqueue` deployment was `Released` but with an **empty
|
|
311
327
|
audience** (~4:41–5:39 pm) so it enqueued nothing; missing opps had no queue row and no worker2 job
|
package/package.json
CHANGED