toga-ai 1.0.391 → 1.0.392
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,7 +6,7 @@ project: Worker
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: architecture
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-07-
|
|
9
|
+
updated: 2026-07-21
|
|
10
10
|
owners: [jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- worker2/Controller/Index.php
|
|
@@ -53,7 +53,8 @@ All table creation, `ALTER` statements, index changes, and seed data — includi
|
|
|
53
53
|
`jobType ENUM('ACTION','CRON')`, `cronJobId`, `dtQueued` (NULL = not yet queued),
|
|
54
54
|
`dtStarted` (committed immediately at check-in), `dtCompleted`, `executionTime`,
|
|
55
55
|
`instanceId`, `isSuccess` (NULL pending/running, 0 fail, 1 success), `action`,
|
|
56
|
-
`parameters` JSON, `failureReason
|
|
56
|
+
`parameters` JSON, `output` (renamed from `failureReason`; **now holds both** failure text
|
|
57
|
+
**and** successful-run results — see the multi-producer rename note below).
|
|
57
58
|
|
|
58
59
|
Derived status: `pending` (`dtQueued IS NULL AND isSuccess IS NULL`) → `queued` → `running`
|
|
59
60
|
(`dtStarted` set, `dtCompleted` NULL) → `succeeded`/`failed`.
|
|
@@ -61,6 +62,21 @@ Derived status: `pending` (`dtQueued IS NULL AND isSuccess IS NULL`) → `queued
|
|
|
61
62
|
**`Core.CronJobs`** — `isActive`, `name`, `schedule` (cron expr, **Central tz**),
|
|
62
63
|
`maxExecutionTime` (watchdog seconds, default 300), `action`, `parameters` JSON.
|
|
63
64
|
|
|
65
|
+
### `WorkerJobs.output` is written by MULTIPLE producers — rename it everywhere at once
|
|
66
|
+
|
|
67
|
+
The outcome column (renamed from `failureReason` → `output`, MEDIUMTEXT) is written by **four**
|
|
68
|
+
places that must change together: the PHP worker check-out (both paths in `Controller/Index.php`),
|
|
69
|
+
the `Retry()` reset (`Worker/Infrastructure/Worker.php`, which clears `output`), and the Python
|
|
70
|
+
**JobScheduler watchdog** Lambda (`LambdaFunctions/JobScheduler/lambda_function.py`, Part B timeout
|
|
71
|
+
UPDATE). Because this is a **rename, not add-and-keep**, old-code/new-column and new-code/old-column
|
|
72
|
+
both break — so the `dbchanges2` `ALTER TABLE Core.WorkerJobs CHANGE failureReason output MEDIUMTEXT
|
|
73
|
+
NULL` must land **simultaneously** with the code deploy, and the watchdog Lambda must be
|
|
74
|
+
**repackaged/redeployed separately** (a Python zip redeploy, not just a code push) or its UPDATE
|
|
75
|
+
errors on the missing column. The PHP `$failureReason` **local variables** were intentionally left
|
|
76
|
+
unchanged (only the SQL column moved). Do **not** touch the same-named-but-unrelated `failureReason`
|
|
77
|
+
fields on other tables: the `Email` table (`Worker/Infrastructure/Email/Send.php`) and
|
|
78
|
+
`Team.TranscriptExports` (`Worker/Team/Transcripts.php`).
|
|
79
|
+
|
|
64
80
|
## The four Lambdas (`worker2/LambdaFunctions/`, Python)
|
|
65
81
|
|
|
66
82
|
`boto3` is in the runtime; `pymysql`, `croniter`, `pytz` are vendored into the zip.
|
|
@@ -91,7 +107,9 @@ New path (`{workerJobId}` present):
|
|
|
91
107
|
3. Register DB_LOGS / DB_CLIENT_LOGS (try/catch → failure marks job failed, returns 200).
|
|
92
108
|
4. Resolve class+method from action (`Clickup/Webhook` → `_Worker_Clickup::Webhook`).
|
|
93
109
|
5. Call `initialize()` if present, then the action with spread parameters.
|
|
94
|
-
6. **Check-out:** `UPDATE dtCompleted, executionTime, isSuccess,
|
|
110
|
+
6. **Check-out:** `UPDATE dtCompleted, executionTime, isSuccess, output`. On success `output` =
|
|
111
|
+
the composed `"[<requestId>] Successfully Executed (<n>s): <return value>"` string (arrays/objects
|
|
112
|
+
`json_encode`d, escaped via `_Database::escape()`); on failure `output` = the failure text. Return 200.
|
|
95
113
|
|
|
96
114
|
Direct-payload path (`action` present, no `workerJobId`): formerly the debug-only "legacy"
|
|
97
115
|
path (untracked, could return HTTP 500). As of 2026-07-07 it is a **first-class tracked
|
|
@@ -211,6 +229,11 @@ the MySQL-first design was departed from **on purpose** here.
|
|
|
211
229
|
|
|
212
230
|
## Change history
|
|
213
231
|
|
|
232
|
+
- 2026-07-21 — `Core.WorkerJobs.failureReason` renamed to `output` and repurposed to capture
|
|
233
|
+
successful run results as well as failures (success writes the composed "Successfully Executed"
|
|
234
|
+
message, return value `json_encode`d). Multi-producer rename: PHP worker (both paths), `Retry()`
|
|
235
|
+
reset, and the JobScheduler watchdog Lambda change together with the `dbchanges2` `CHANGE`
|
|
236
|
+
migration; watchdog Lambda needs a separate redeploy. (jcardinal)
|
|
214
237
|
- 2026-07-09 — Added the "long-running AI actions — sync vs. async writes" rule: reads-back
|
|
215
238
|
writes go before the AI call, synchronous+committed; post-AI status writes go async.
|
|
216
239
|
Distilled from the Talos Graph-direct pipeline (async pre-AI dedupe writes weren't durable
|
|
@@ -6,7 +6,7 @@ project: Worker
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
9
|
+
updated: 2026-07-21
|
|
10
10
|
owners: [jcardinal, dfranks, mhammontree]
|
|
11
11
|
files:
|
|
12
12
|
- worker2/Worker/
|
|
@@ -133,11 +133,17 @@ Use realistic placeholder values, not empty strings/nulls.
|
|
|
133
133
|
|
|
134
134
|
The EB worker dispatcher (`Controller/Index.php::worker()`) wraps your action call in
|
|
135
135
|
`try { } catch (\Throwable $e)`:
|
|
136
|
-
- **Returns normally** → `WorkerJobs.isSuccess = 1`, `dtCompleted` set
|
|
137
|
-
|
|
136
|
+
- **Returns normally** → `WorkerJobs.isSuccess = 1`, `dtCompleted` set, and the composed success
|
|
137
|
+
message (`"[<requestId>] Successfully Executed (<n>s): <return value>"`, arrays/objects
|
|
138
|
+
`json_encode`d) written to the `output` column.
|
|
139
|
+
- **Throws** (any `Throwable`, incl. `Error`) → `isSuccess = 0`, `output` = message +
|
|
138
140
|
`file:line` + full stack trace. (Two earlier phases — DB-logs registration and `initialize()` —
|
|
139
141
|
fail the same way.)
|
|
140
142
|
|
|
143
|
+
> The outcome column on `Core.WorkerJobs` is named **`output`** (renamed from `failureReason`).
|
|
144
|
+
> It now captures **both** success results and failure text. See
|
|
145
|
+
> [architecture.md](../architecture.md) for the multi-producer rename gotcha.
|
|
146
|
+
|
|
141
147
|
Crucially, the worker **always returns HTTP 200, even on a throw**, so SQS deletes the message
|
|
142
148
|
immediately. **There is no DLQ and no automatic retry.** A throw makes the failure *visible* (a
|
|
143
149
|
failed `WorkerJobs` row to alert on) — it does **not** re-run the job.
|
|
@@ -169,6 +175,9 @@ be reattempted.
|
|
|
169
175
|
commit-before-SQS transaction pattern that the worker relies on.
|
|
170
176
|
|
|
171
177
|
## Change history
|
|
178
|
+
- 2026-07-21 — `WorkerJobs.failureReason` column renamed to **`output`** and repurposed to store
|
|
179
|
+
successful execution results as well as failure text; success now writes the composed
|
|
180
|
+
"Successfully Executed" message (return value `json_encode`d for arrays/objects). (jcardinal)
|
|
172
181
|
- 2026-06-30 — Added the **`DB_CLIENT` auto-registration gotcha**: the dispatcher registers only
|
|
173
182
|
`DB_CLIENT_LOGS`, so a worker loading a `Client_*` model must call
|
|
174
183
|
`_Database::registerClientDatabases($clientId, $environment)` itself (proven by
|
package/package.json
CHANGED