Labels Applied table lookup and re-processing #
I've changed the use of the labels applied as an event log, it is append-only. The unique key is (labeler, seq, uri, label), I decided not to use a hash column as I don't think it would bring any benefit and xxhash would be one more dependency.
A negation or re-application is a new row with its
own seq rather than an in-place update, so the audit history survives.
export const labelsApplied = sqliteTable(
"labels_applied",
{
id: integer("id").primaryKey({ autoIncrement: true }),
seq: integer("seq"),
labeler: text("labeler").notNull(),
uri: text("uri"),
did: text("did").notNull(),
label: text("label").notNull(),
action: text("action").notNull(),
negated: integer("negated", { mode: "boolean" }).default(false).notNull(),
dateApplied: integer("date_applied", { mode: "timestamp" }).notNull(),
},
(t) => [
uniqueIndex("labels_applied_event_idx").on(t.labeler, t.seq, t.uri, t.label),
index("labels_applied_did_idx").on(t.did),
],
);
Your concern about the lookup should be addressed with the per-did index, all queries should hit it.
I am using it to understand whether a particular label was already applied. We record the label in the labels applied table at the end of the processing of actions. This means the actions themselves need to be "idempotent" in the sense that if an action is applied and an error occurs afterwards, or the process crashes and doesn't finish the batch processing, replaying that label must succeed (or re-doing the action must be acceptable).
- Takedown : checks to take_down_issued_date
- Ozone tagging : Ozone's externalId (now the same string as the event key) means the tag emission is idempotent as it's deduped on the Ozone side
- Emails actually resend
Also fixes a latent collision
in the old key: two record labels on different records of the same repo used to overwrite
each other's row, and uri actually gets populated now.
Migration is additive (ADD COLUMN seq + two indexes, no table rebuild), auto-applies on
startup like the others. Existing rows keep seq/uri NULL — NULLs are distinct in SQLite
unique indexes so they can't collide with new rows or each other (tested the migration over
a db with legacy data). Old code also runs fine against the new schema, so rolling back
doesn't need a schema rollback.
handleNewLabel refactor #
There is also a small refactor of handleNewLabel (735ce88) that moves the actions behind per-action handlers. Each Action handler lives in its own file, and are created once at startup. This makes the code for the label handler more readable.