mirror of
https://github.com/kuhyx/todo-app.git
synced 2026-11-10 18:07:03 +01:00
Bulk update: diff generated fields only
planBulkUpdate compared fresh field values with the stored text, so a peer's "...00Z" created_at (or a web build's millisecond date) read as a change and got a fresh clock, erasing the created_by node signal; a record without a priority field got one written. Compare the note's own generated fields before and after instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzxdWXdsB7CQPNXVN829G1
This commit is contained in:
parent
757c54beda
commit
4c77dd5d2e
@ -31,6 +31,10 @@ Log planBulkUpdate(
|
||||
final note = noteFromRecord(current);
|
||||
final next = note.copyWith(priority: priority, status: status);
|
||||
if (next.priority == note.priority && next.status == note.status) continue;
|
||||
// Generated against generated, never against the stored text: a peer's
|
||||
// `...00Z` (or a web build's millisecond date) would otherwise read as
|
||||
// a change and get a fresh clock, erasing the `created_at` node signal.
|
||||
final before = noteFields(note, hlc);
|
||||
plan[id] = Record(
|
||||
id: id,
|
||||
fields: {
|
||||
@ -38,7 +42,7 @@ Log planBulkUpdate(
|
||||
next.copyWith(updatedAt: now),
|
||||
hlc,
|
||||
).entries)
|
||||
if (current.fields[key]?.$1 != value.$1) key: value,
|
||||
if (before[key]?.$1 != value.$1) key: value,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 1.0.68+1
|
||||
version: 1.0.69+1
|
||||
|
||||
environment:
|
||||
sdk: ^3.12.2
|
||||
|
||||
@ -75,6 +75,33 @@ void main() {
|
||||
expect((await repo.listNotes()).single.status, Status.done);
|
||||
});
|
||||
|
||||
test(
|
||||
'a stored value Dart would format differently keeps its clock',
|
||||
() async {
|
||||
final (repo, _) = await _open();
|
||||
final peer = Hlc(wallTimeMs: 1000, counter: 0, nodeId: 'mcp');
|
||||
// A peer's (or a web build's) timestamp text, and no priority field.
|
||||
await repo.importLog({
|
||||
'a': Record(
|
||||
id: 'a',
|
||||
fields: {
|
||||
'text': ('A', peer),
|
||||
'status': (0, peer),
|
||||
'created_at': ('2026-01-01T00:00:00Z', peer),
|
||||
'updated_at': ('2026-01-01T00:00:00Z', peer),
|
||||
},
|
||||
),
|
||||
});
|
||||
|
||||
await repo.bulkUpdate({'a'}, status: Status.done);
|
||||
|
||||
final fields = repo.exportLog()['a']!.fields;
|
||||
expect(fields['created_at'], ('2026-01-01T00:00:00Z', peer));
|
||||
expect(fields.containsKey('priority'), isFalse);
|
||||
expect(fields['status']!.$2.nodeId, 'dev');
|
||||
},
|
||||
);
|
||||
|
||||
test('no write when nothing changes or ids are unknown/deleted', () async {
|
||||
final (repo, p) = await _open();
|
||||
await repo.upsert(noteFixture('a', 'A'));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user