Skip to content

Commit c8b4e70

Browse files
committed
Week 3 Day 19: Fix CI (assets + lint), validate HEAD sync, and update timeline
1 parent b880a86 commit c8b4e70

File tree

7 files changed

+80
-4
lines changed

7 files changed

+80
-4
lines changed

PROJECT_TIMELINE.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,4 +1053,17 @@ Files Created/Modified:
10531053
Notes:
10541054
- Full system verification (Day 15-18) successfully passed, confirming P2P broadcast, deduplication, sync, and causal consistency.
10551055

1056+
DAY 19:
1057+
Date:
1058+
Focus: Head-Based Synchronization
1059+
1060+
Content:
1061+
• Implemented HEAD exchange protocol to compare distributed state across peers
1062+
• Built missing message detection using DAG head comparison
1063+
• Added message_request and message_response protocols
1064+
• Ensured forward causal delivery using dependency-aware ordering
1065+
• Integrated sync with GossipLog for consistency-safe application
1066+
• Prevented redundant data transfer by requesting only missing messages
1067+
• Enabled full peer-to-peer state convergence without central server
1068+
10561069
------------------------------------------------------------

mobile_app/assets/tiles/.keep

Whitespace-only changes.

mobile_app/lib/data/repositories/incident_repository.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class IncidentRepository {
128128
});
129129
} catch (e) {
130130
// Failed to push (e.g. offline), keeps 'queued'
131-
print('Sync failed, will retry later: $e');
131+
debugPrint('Sync failed, will retry later: $e');
132132
}
133133
}
134134

mobile_app/lib/features/map/map_screen.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,8 @@ class _MapScreenState extends State<MapScreen> {
504504
void _centerOnMyLocation() async {
505505
final locService = context.read<LocationService>();
506506
final loc = await locService.getCurrentLocation();
507-
if (loc != null && mounted) {
507+
if (!mounted) return;
508+
if (loc != null) {
508509
_mapController.move(loc, 16.0);
509510
} else {
510511
ScaffoldMessenger.of(context).showSnackBar(

mobile_app/lib/features/map/map_service.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ final LatLngBounds indiaBounds = LatLngBounds(
6060
/// Service that manages offline tile serving via MBTiles and tile URL resolution.
6161
///
6262
/// Fallback chain (never leaves tile URL empty):
63-
/// 1. Local MBTiles server → http://localhost:<port>/tiles/{z}/{x}/{y}.png
63+
/// 1. Local MBTiles server → http://localhost:[port]/tiles/{z}/{x}/{y}.png
6464
/// 2. Config remote tile URL from config.json `backend_tile_url`
6565
/// 3. Hard fallback: https://tile.openstreetmap.org/{z}/{x}/{y}.png
6666
class MapService {

mobile_app/lib/widgets/navigation_steps_panel.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class NavigationStepsPanel extends StatelessWidget {
8080
: ListView.separated(
8181
controller: scrollController,
8282
itemCount: steps.length,
83-
separatorBuilder: (_, __) => const Divider(height: 1),
83+
separatorBuilder: (context, index) => const Divider(height: 1),
8484
itemBuilder: (context, index) {
8585
final step = steps[index];
8686
final distanceStr = step.distance >= 1000

mobile_app/test/gossip_log_service_test.dart

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,5 +226,67 @@ void main() {
226226
expect(received[1].msgId, 'm2');
227227
expect(received[2].msgId, 'm3');
228228
});
229+
230+
test('Day 19 Integration: Multi-device convergence (A -> B -> C)', () async {
231+
final serviceA = GossipLogService();
232+
final serviceB = GossipLogService();
233+
final serviceC = GossipLogService();
234+
235+
// A creates 3 incidents
236+
final m1 = _makeEnvelope(msgId: 'm1', clock: 1);
237+
serviceA.recordSent(m1);
238+
final m2 = _makeEnvelope(msgId: 'm2', clock: 2, prevMsgIds: ['m1']);
239+
serviceA.recordSent(m2);
240+
final m3 = _makeEnvelope(msgId: 'm3', clock: 3, prevMsgIds: ['m2']);
241+
serviceA.recordSent(m3);
242+
243+
expect(serviceA.logSize, 3);
244+
245+
// A connects to B. B discovers it's missing M1, M2, M3.
246+
// B sends head_exchange with empty heads. A sends head_exchange with [m3].
247+
final missingInB = serviceB.findMissingMessages(serviceA.getHeads());
248+
expect(missingInB, ['m3']);
249+
250+
// B requests m3. A sends m3.
251+
final fetched3 = serviceA.fetchAndSortMessages(['m3']);
252+
final depsB = serviceB.receive(fetched3.first);
253+
expect(depsB, ['m2']);
254+
255+
// B requests m2. A sends m2.
256+
final fetched2 = serviceA.fetchAndSortMessages(['m2']);
257+
final depsB2 = serviceB.receive(fetched2.first);
258+
expect(depsB2, ['m1']);
259+
260+
// B requests m1. A sends m1.
261+
final fetched1 = serviceA.fetchAndSortMessages(['m1']);
262+
final depsB3 = serviceB.receive(fetched1.first);
263+
expect(depsB3, isEmpty);
264+
265+
// B now has all messages
266+
expect(serviceB.logSize, 3);
267+
expect(serviceB.getHeads(), ['m3']);
268+
269+
// B connects to C. C only has m1.
270+
serviceC.receive(m1);
271+
final missingInC = serviceC.findMissingMessages(serviceB.getHeads());
272+
expect(missingInC, ['m3']);
273+
274+
// C requests m3, receives from B.
275+
final fetchedC3 = serviceB.fetchAndSortMessages(['m3']);
276+
final depsC = serviceC.receive(fetchedC3.first);
277+
expect(depsC, ['m2']);
278+
279+
// C requests m2, receives from B.
280+
final fetchedC2 = serviceB.fetchAndSortMessages(['m2']);
281+
final depsC2 = serviceC.receive(fetchedC2.first);
282+
expect(depsC2, isEmpty); // C already had m1. So m2 unblocks m3!
283+
284+
// C now has all messages
285+
expect(serviceC.logSize, 3);
286+
expect(serviceC.getHeads(), ['m3']);
287+
288+
expect(serviceA.getHeads(), serviceB.getHeads());
289+
expect(serviceB.getHeads(), serviceC.getHeads());
290+
});
229291
});
230292
}

0 commit comments

Comments
 (0)