You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
| GitHub 5xx or 429 | raises — retried, then DLQ |
44
+
| No usable credential | raises — retried, then DLQ |
45
+
| Malformed payload | raises — retried, then DLQ |
46
+
| GitHub 404 (log has aged out), 401, 403 | returns `stored: false`, no retry |
47
+
| Classifier call fails or times out | returns `classified: false`, no retry |
48
+
49
+
The bottom two are deliberate. A log GitHub has already dropped does not come
50
+
back on the third attempt, and re-running a whole download to retry a classifier
51
+
handoff would re-fetch megabytes to redo something that takes milliseconds.
52
+
`stored: false` is therefore not visible on the DLQ; if you want to alarm on it,
53
+
match the terminal `ERROR <status> downloading log` line specifically. Do **not**
54
+
alarm on `ERROR` generally: `installation_token` logs one every time it falls
55
+
back to the PAT pool, which is a path that then usually succeeds.
56
+
34
57
## Classification
35
58
36
59
After a log is stored, `log_classifier` is called through its function URL —
37
60
byte for byte the call `github-status-test` makes today.
38
61
39
-
That call is synchronous. Function URLs only support the `RequestResponse`
40
-
invocation type, so this function's duration includes the classification, and
41
-
`github-status-test`'s 274s/344s/400s/900s duration maxima come from exactly
42
-
this. **Keep the timeout at 900s**: on a slow classification a shorter one would
43
-
kill the invocation mid-wait, and since callers invoke asynchronously, Lambda
44
-
would then retry the whole thing and re-download the log.
62
+
Function URLs only support the `RequestResponse` invocation type, so there is no
63
+
way to ask for fire-and-forget. `CLASSIFIER_TIMEOUT` gets close enough: after 30s
64
+
this stops waiting for the reply. Disconnecting does not cancel the classifier —
65
+
it runs to completion regardless — so nothing is lost by hanging up, and
66
+
`github-status-test`'s 274s/344s/400s/900s duration maxima do not carry over.
67
+
68
+
That bound is load-bearing, not tidiness. `urlopen` with no `timeout` has none at
69
+
all, so a connection that is accepted and never answered raises nothing and burns
70
+
the entire function timeout. Since callers invoke asynchronously, Lambda counts
71
+
that as a failure and replays the whole invocation twice more, re-downloading the
72
+
same log each time and eventually DLQ-ing a job whose log was archived fine on
73
+
the first attempt. `github-status-test` does hit its 900s ceiling, so this is an
74
+
observed tail, not a theoretical one.
45
75
46
-
Unlike in `github-status-test` the tail is no longer harmful. There it ran behind
47
-
API Gateway on the webhook's critical path, so a slow classification risked a
48
-
GitHub webhook timeout. Here the caller has already returned, and a long
49
-
invocation costs GB-seconds and a concurrency slot, nothing more.
76
+
With the wait bounded, every step has an explicit ceiling — two 30s log fetches
77
+
at most, then a 30s classifier call — so a **300s function timeout** is
78
+
comfortable, rather than the 900s `github-status-test` needs.
50
79
51
80
The way out is `lambda:InvokeFunction` with `InvocationType: "Event"`, which
52
81
needs `log_classifier` to accept a plain `{"job_id", "repo"}` payload — it
@@ -82,7 +111,7 @@ on the repo.
82
111
83
112
| Env var | Required | Purpose |
84
113
| --- | --- | --- |
85
-
|`GITHUB_APP_ID`| no |App id used to mint installation tokens (e.g. `4550824`, `pytorch-bot-preview`)|
114
+
|`GITHUB_APP_ID`| no |Numeric app id used to mint installation tokens, e.g. `4550824` — the id of the `pytorch-bot-preview` app. Must be the number: it goes through `int()`, so an app slug fails|
86
115
|`GITHUB_APP_PRIVATE_KEY`| no | The app's private key, base64-encoded PEM (same encoding torchci uses) |
87
116
|`GITHUB_TOKENS`| yes | Comma-separated PAT pool, used as the fallback and when no app is configured |
88
117
@@ -109,16 +138,17 @@ Notes on the app path:
109
138
Not done by CI. Needed before the deploy workflow can run.
110
139
111
140
1. Create the function: python3.12, x86_64, handler `lambda_function.lambda_handler`,
112
-
512 MB, **900s timeout** — matching `github-status-test`, because the
113
-
synchronous classifier call means a slow classification is a slow invocation.
141
+
512 MB, **300s timeout** — every step is individually bounded, so this does
142
+
not need `github-status-test`'s 900s. See Classification above.
114
143
2. Give its execution role `s3:PutObject` on `arn:aws:s3:::ossci-raw-job-status/log/*`
115
144
plus the usual CloudWatch Logs permissions. No `lambda:InvokeFunction` is
116
145
needed while the classifier is reached over its function URL.
117
146
3. Set the env vars above. Prefer fresh credentials over copying
118
147
`github-status-test`'s, whose PATs sit in plaintext env vars and are due for
119
148
rotation.
120
-
4. Configure an on-failure destination or DLQ, and alarm on it. That queue is the
121
-
only signal that a trunk-only job lost its log.
149
+
4. Configure an on-failure destination or DLQ, and alarm on it. For a trunk-only
150
+
job that is the only signal its log went missing — Dr.CI's self-heal only
151
+
covers PR jobs. See "What fails how" for what does and does not land there.
122
152
5. Add the invoke grant for torchci, and nothing else:
0 commit comments