Repository navigation
Mirror ModerationCase entities to SQL. - #9717
Conversation
isoos
commented
Oct 16, 2026
- Tracking the migration of Datastore entities to SQL #9645
- Also includes the commit from Fix: store the grounds information on the ModerationCase #9714
bb4dfe7 to
c4ecb58
Compare
sigurdm
left a comment
There was a problem hiding this comment.
LGTM!
Now that 000021_moderation_case.sql is in this PR and rebased on #9720, we could also uncomment 'moderation-cases-chk-resolved' and 'moderation-cases-fk-appealed' in app/lib/admin/actions/migrate_dry_run.dart (and drop - Also includes the commit from #9714 from the PR description).
| for (var i = 0; i < entries.length; i++) { | ||
| final e = entries[i]; | ||
| await db.moderationActionLogs | ||
| .upsertValue( | ||
| caseId: mc.caseId, | ||
| logId: Ulid(millis: e.timestamp.millisecondsSinceEpoch).toUuid(), | ||
| createdAt: e.timestamp, | ||
| subject: e.subject, | ||
| action: e.moderationAction.name, | ||
| note: e.note, | ||
| ) | ||
| .execute(); | ||
| } |
There was a problem hiding this comment.
Ulid(millis: ...) uses the default UlidFactory() where monotonic is false, so each call draws 80 fresh random bits. If two action log entries share the same millisecond (e.g. under a fixed clock in tests, or if two iterations of the loop in moderation_case_sql_test.dart execute within the same millisecond), there is a 50% chance their logIds sort in the opposite order of entries, causing _isModerationCaseInSql to return false and expectModerationCasesInSqlMatchDatastore() to flake.
Could we use a local monotonic UlidFactory here (and drop the unused loop index i)?
| for (var i = 0; i < entries.length; i++) { | |
| final e = entries[i]; | |
| await db.moderationActionLogs | |
| .upsertValue( | |
| caseId: mc.caseId, | |
| logId: Ulid(millis: e.timestamp.millisecondsSinceEpoch).toUuid(), | |
| createdAt: e.timestamp, | |
| subject: e.subject, | |
| action: e.moderationAction.name, | |
| note: e.note, | |
| ) | |
| .execute(); | |
| } | |
| final ulidFactory = UlidFactory( | |
| monotonic: true, | |
| monotonicBufferBits: 1, | |
| incrementMillisOnOverflow: true, | |
| ); | |
| for (final e in entries) { | |
| await db.moderationActionLogs | |
| .insertValue( | |
| caseId: mc.caseId, | |
| logId: ulidFactory | |
| .next(millis: e.timestamp.millisecondsSinceEpoch) | |
| .toUuid(), | |
| createdAt: e.timestamp, | |
| subject: e.subject, | |
| action: e.moderationAction.name, | |
| note: e.note, | |
| ) | |
| .execute(); | |
| } |
| final mc = await adminBackend.lookupModerationCase(caseId); | ||
| await adminBackend.mirrorModerationCaseToSqlById(caseId); |
There was a problem hiding this comment.
Nit: since mc was just looked up on line 78 (and similarly returned from the transaction in moderation_case_resolve.dart:131), we can pass mc! directly to mirrorModerationCaseToSql(mc) to avoid a second Datastore lookup:
| final mc = await adminBackend.lookupModerationCase(caseId); | |
| await adminBackend.mirrorModerationCaseToSqlById(caseId); | |
| final mc = (await adminBackend.lookupModerationCase(caseId))!; | |
| await adminBackend.mirrorModerationCaseToSql(mc); |