Skip to content

Instantly share code, notes, and snippets.

@xsahil03x
Created June 2, 2021 06:39
Show Gist options
  • Save xsahil03x/a0811e3bb541a5cbff3e74f2a003c07f to your computer and use it in GitHub Desktop.
Save xsahil03x/a0811e3bb541a5cbff3e74f2a003c07f to your computer and use it in GitHub Desktop.

Revisions

  1. xsahil03x created this gist Jun 2, 2021.
    119 changes: 119 additions & 0 deletions event_sync_helper.dart
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,119 @@
    abstract class EventSyncHelper {
    void startSession();

    Future<void> sendEvent(Event event);

    Future<VoidResult> syncRemainingEvents();

    void endSession();
    }

    class EventSyncHelperImpl implements EventSyncHelper {
    final EventRepository eventRepository;
    final AppPreferencesHelper prefsHelper;
    final NetworkInfo networkInfo;
    final ApiBaseHelper apiHelper;

    StreamSubscription _connectivityChangeSubscription;

    EventSyncHelperImpl({
    @required this.eventRepository,
    @required this.prefsHelper,
    @required this.networkInfo,
    @required this.apiHelper,
    });

    Future<VoidResult> _postEventToServer(Event event) async {
    try {
    final res = await apiHelper.post(
    ApiPaths.postEvent,
    json.encode(event.toJson(postToServer: true)),
    );
    if (res.statusCode == 200) {
    return VoidResult.success();
    } else {
    return VoidResult.failure(reason: 'Failed to post event : $event');
    }
    } catch (e, stk) {
    logError(e, stacktrace: stk);
    return VoidResult.failure(reason: 'Failed to post event : ${e.message}');
    }
    }

    Future<void> _syncAllEvents() async {
    if (await eventRepository.isEventUnSynced()) {
    logMessage('Syncing all events');
    final sessionId = prefsHelper.sessionId;
    final unSyncedEvents =
    await eventRepository.getAllUnSyncedEventsForSession(sessionId);
    for (final event in unSyncedEvents) {
    final result = await _postEventToServer(event);
    result.when(
    success: (_) {
    eventRepository.setEventAsSynced(event.eventId);
    logMessage('Event successfully posted : $event');
    },
    failure: (error) {
    logMessage(error.reason);
    throw EventSyncFailedError(error.reason);
    },
    );
    }
    } else {
    logMessage('All events are already synced');
    }
    }

    @override
    void startSession() {
    logMessage('Event sync session started');
    _connectivityChangeSubscription =
    Connectivity().onConnectivityChanged.distinct().listen(
    (result) async {
    logMessage('Connectivity changed : $result');
    if (result != ConnectivityResult.none) {
    final isDeviceConnected = await networkInfo.isConnected;
    if (isDeviceConnected) {
    _syncAllEvents();
    } else
    logMessage('Device is not connected to the internet');
    }
    },
    );
    }

    @override
    Future<void> sendEvent(Event event) async {
    final result = await _postEventToServer(event);
    result.when(
    success: (_) => logMessage('Event successfully posted : $event'),
    failure: (error) {
    eventRepository.saveEventToDb(event);
    logMessage(error.reason);
    },
    );
    }

    @override
    Future<VoidResult> syncRemainingEvents() async {
    try {
    await _syncAllEvents();
    return VoidResult.success();
    } catch (e, stk) {
    logError(e, stacktrace: stk);
    return VoidResult.failure(reason: '${e.message}');
    }
    }

    @override
    void endSession() {
    _connectivityChangeSubscription?.cancel();
    logMessage('Event sync session stopped');
    }
    }

    class EventSyncFailedError implements Exception {
    final String message;

    const EventSyncFailedError(this.message);
    }