add todo list
This commit is contained in:
parent
63e01c5b6d
commit
3b7447289f
1 changed files with 110 additions and 0 deletions
110
TODO.md
Normal file
110
TODO.md
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
# TODO
|
||||
|
||||
Ordered roughly by importance. Items near the top either caused real
|
||||
failures already or block going live.
|
||||
|
||||
## 1. Deletions never propagate — weekly full resync and prune
|
||||
|
||||
`_since` returns records ST considers *updated*. A deleted user is not
|
||||
returned at all, so their row stays in `people` forever. This has already
|
||||
caused two failed runs: once with a deleted rep chosen as `reps[0]` (45
|
||||
identical 404s), once with a deleted member failing mid-run.
|
||||
|
||||
started := time.Now().Unix()
|
||||
users, _ := client.ListUsers(ctx, 0) // full pull, ~176 requests
|
||||
store.UpsertPeople(users, eligible)
|
||||
store.PruneStale(started) // DELETE FROM people WHERE synced_at < ?
|
||||
store.SetLastSync(started)
|
||||
|
||||
Guards:
|
||||
|
||||
- Only prune after a `since=0` pass. A delta pass refreshes a handful of
|
||||
rows and would delete everything else.
|
||||
- Refuse to prune if it would remove more than a few percent of the table.
|
||||
A bug that silently empties the cache takes out every reconcile until
|
||||
someone notices.
|
||||
|
||||
## 2. Delta sync at the start of each reconcile
|
||||
|
||||
One request, usually returning nothing. Eliminates the whole class of
|
||||
stale-cache confusion that came up four separate times during testing:
|
||||
a new rep not yet cached, a rep whose flag was removed still being
|
||||
chosen, a department change invisible to the reconciler.
|
||||
|
||||
## 3. Small fixes, one commit
|
||||
|
||||
- **`failed` in the reconcile summary.** Run 10 logged
|
||||
`0 assigned, 0 skipped` after 45 failures. A wholly failed run is
|
||||
currently indistinguishable from an empty one.
|
||||
- **Verify the agent before the loop.** One `GetUser(agent)` at the top
|
||||
of `reconcile`; abort with a clear message rather than failing once per
|
||||
member.
|
||||
- **Prune a member's cache row on a 404 from `AssignAgent`.** Reactive
|
||||
and self-healing: a stale row fails once instead of on every future run
|
||||
of that department.
|
||||
- **Live `IsRep` check in the handler.** Chapter and department come from
|
||||
a live `GetUser`, but nothing checks whether the person is still a rep.
|
||||
Someone whose flag was removed can still trigger a full reconcile.
|
||||
- **Add `sqlite` to the Dockerfile runtime stage.** Inspecting `skips`,
|
||||
`runs`, or `sync_state` currently means a rebuild or a throwaway
|
||||
container mounted on the volume.
|
||||
|
||||
## 4. Before going live
|
||||
|
||||
- **`VACUUM INTO` on a timer.** Volume snapshots of a live WAL database
|
||||
are not safe to restore. The skip log is the only thing here that
|
||||
cannot be regenerated.
|
||||
- **Turn off `DRY_RUN`, redeploy.**
|
||||
- **Backfill.** The webhook only fires when a rep is *newly* assigned the
|
||||
role, so the existing 119 never trigger it. Run with `DRY_RUN` set
|
||||
first and count the assignments in the log; expect roughly 2,300.
|
||||
|
||||
sqlite3 worker.db "SELECT id FROM people WHERE is_rep = 1;" | while read id; do
|
||||
curl -s -o /dev/null -X POST "https://HOST/webhook?id=$id&s=$SECRET"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
## 5. Deferred design decisions
|
||||
|
||||
- **Nightly sweep.** Without it, a rep who steps down keeps their
|
||||
assignments and their replacement inherits nobody. Members added after
|
||||
their department's rep signed up also stay unassigned until something
|
||||
triggers that department again. Rep replacement was described as
|
||||
frequent, so this matters more than the member-churn case.
|
||||
- **Round-robin split for co-repped departments.** 14 departments have
|
||||
two reps, covering 302 members, 9 of them at chapter 607. The second
|
||||
rep currently gets nobody and sees an empty list with no error.
|
||||
`RepsFor` already returns every rep sorted by ID, so this is a change
|
||||
to how the agent is picked, not a restructuring. Blocked by the
|
||||
fill-only rule, not by complexity.
|
||||
- **Raise the fill-only consequence upstream.** The rule came from
|
||||
outside the project. The concrete cost is now measurable: 14 reps at
|
||||
three campuses will open the app to an empty list.
|
||||
- **Schema migrations.** `CREATE TABLE IF NOT EXISTS` does not add
|
||||
columns to an existing table. Changing the schema currently means
|
||||
deleting the database and re-syncing, which will not be an option in
|
||||
production.
|
||||
- **License.** AGPLv3 if the goal is that other associations running a
|
||||
modified copy must share changes; Apache-2.0 if the goal is that they
|
||||
actually adopt it. Check first whether this is yours to license given
|
||||
it is faculty association work.
|
||||
|
||||
## 6. Open questions for ST support
|
||||
|
||||
- Do a deleted or demoted rep's agent assignments stay active? This
|
||||
decides whether departing reps permanently strand their members under
|
||||
fill-only. Untested: the assignments observed as inactive were
|
||||
deactivated by hand.
|
||||
- `DELETE /agent_assignments/{id}` returns 404 on a row that
|
||||
`GET /agent_assignments/{id}` returns fine. Either the path takes
|
||||
something else or the handler is broken.
|
||||
|
||||
## 7. README corrections
|
||||
|
||||
- Work List rows are materialized by an ST job running on the half hour.
|
||||
A new rep sees an empty list for up to 30 minutes after their
|
||||
assignments are written. Confirmed: rows appeared exactly at :30. Worth
|
||||
saying in whatever onboarding message reps get, or they will report it
|
||||
as broken.
|
||||
- Remove any claim that deleting a person deactivates their assignments.
|
||||
That was done manually and the actual behaviour is unknown.
|
||||
Loading…
Add table
Add a link
Reference in a new issue