private static IStateResult configurePushTransitionsForTimeEntries(
            TransitionHandlerProvider transitions,
            ITogglDatabase database,
            ITogglApi api,
            ITogglDataSource dataSource,
            IScheduler scheduler,
            IStateResult entryPoint,
            IObservable <Unit> delayCancellation)
        {
            var rnd         = new Random();
            var apiDelay    = new RetryDelayService(rnd);
            var statusDelay = new RetryDelayService(rnd);

            var push              = new PushTimeEntriesState(database.TimeEntries);
            var pushOne           = new PushOneEntityState <IDatabaseTimeEntry>();
            var create            = new CreateTimeEntryState(api, dataSource.TimeEntries);
            var update            = new UpdateTimeEntryState(api, dataSource.TimeEntries);
            var delete            = new DeleteTimeEntryState(api, database.TimeEntries);
            var deleteLocal       = new DeleteLocalTimeEntryState(database.TimeEntries);
            var unsyncable        = new UnsyncableTimeEntryState(dataSource.TimeEntries);
            var checkServerStatus = new CheckServerStatusState(api, scheduler, apiDelay, statusDelay, delayCancellation);
            var finished          = new ResetAPIDelayState(apiDelay);

            return(configurePush(transitions, entryPoint, push, pushOne, create, update, delete, deleteLocal, unsyncable, checkServerStatus, finished));
        }
        private static void configurePullTransitions(
            TransitionHandlerProvider transitions,
            ITogglDatabase database,
            ITogglApi api,
            ITogglDataSource dataSource,
            ITimeService timeService,
            StateResult entryPoint)
        {
            var fetchAllSince            = new FetchAllSinceState(database, api, timeService);
            var persistWorkspaces        = new PersistWorkspacesState(database.Workspaces, database.SinceParameters);
            var persistWorkspaceFeatures = new PersistWorkspacesFeaturesState(database.WorkspaceFeatures, database.SinceParameters);
            var persistTags        = new PersistTagsState(database.Tags, database.SinceParameters);
            var persistClients     = new PersistClientsState(database.Clients, database.SinceParameters);
            var persistProjects    = new PersistProjectsState(database.Projects, database.SinceParameters);
            var persistTimeEntries = new PersistTimeEntriesState(dataSource.TimeEntries, database.SinceParameters, timeService);
            var persistTasks       = new PersistTasksState(database.Tasks, database.SinceParameters);

            transitions.ConfigureTransition(entryPoint, fetchAllSince.Start);
            transitions.ConfigureTransition(fetchAllSince.FetchStarted, persistWorkspaces.Start);
            transitions.ConfigureTransition(persistWorkspaces.FinishedPersisting, persistWorkspaceFeatures.Start);
            transitions.ConfigureTransition(persistWorkspaceFeatures.FinishedPersisting, persistTags.Start);
            transitions.ConfigureTransition(persistTags.FinishedPersisting, persistClients.Start);
            transitions.ConfigureTransition(persistClients.FinishedPersisting, persistProjects.Start);
            transitions.ConfigureTransition(persistProjects.FinishedPersisting, persistTasks.Start);
            transitions.ConfigureTransition(persistTasks.FinishedPersisting, persistTimeEntries.Start);
        }
        private static IStateResult configureUpdateOnlyPush <T>(
            TransitionHandlerProvider transitions,
            IStateResult entryPoint,
            BasePushState <T> push,
            PushOneEntityState <T> pushOne,
            BaseUpdateEntityState <T> update,
            BaseUnsyncableEntityState <T> markUnsyncable,
            CheckServerStatusState checkServerStatus,
            ResetAPIDelayState finished)
            where T : class, IBaseModel, IDatabaseSyncable
        {
            transitions.ConfigureTransition(entryPoint, push.Start);
            transitions.ConfigureTransition(push.PushEntity, pushOne.Start);
            transitions.ConfigureTransition(pushOne.UpdateEntity, update.Start);

            transitions.ConfigureTransition(pushOne.CreateEntity, new InvalidTransitionState($"Creating is not supported for {typeof(T).Name} during Push sync.").Start);
            transitions.ConfigureTransition(pushOne.DeleteEntity, new InvalidTransitionState($"Deleting is not supported for {typeof(T).Name} during Push sync.").Start);
            transitions.ConfigureTransition(pushOne.DeleteEntityLocally, new InvalidTransitionState($"Deleting locally is not supported for {typeof(T).Name} during Push sync.").Start);

            transitions.ConfigureTransition(update.ClientError, markUnsyncable.Start);
            transitions.ConfigureTransition(update.ServerError, checkServerStatus.Start);
            transitions.ConfigureTransition(update.UnknownError, checkServerStatus.Start);

            transitions.ConfigureTransition(checkServerStatus.Retry, checkServerStatus.Start);
            transitions.ConfigureTransition(checkServerStatus.ServerIsAvailable, push.Start);

            transitions.ConfigureTransition(update.UpdatingSucceeded, finished.Start);

            transitions.ConfigureTransition(finished.PushNext, push.Start);

            return(push.NothingToPush);
        }
Exemplo n.º 4
0
 protected void Reset()
 {
     Queue        = new SyncStateQueue();
     Transitions  = new TransitionHandlerProvider();
     Scheduler    = new TestScheduler();
     StateMachine = new StateMachine(Transitions, Scheduler, Substitute.For <ISubject <Unit> >());
     EntryPoints  = new StateMachineEntryPoints();
     Orchestrator = new StateMachineOrchestrator(StateMachine, EntryPoints);
     SyncManager  = new SyncManager(Queue, Orchestrator);
 }
Exemplo n.º 5
0
 private static void configurePushTransitions(
     TransitionHandlerProvider transitions,
     ITogglDatabase database,
     ITogglApi api,
     ITogglDataSource dataSource,
     IScheduler scheduler,
     StateResult entryPoint)
 {
     configurePushTransitionsForTimeEntries(transitions, database, api, dataSource, scheduler, entryPoint);
 }
Exemplo n.º 6
0
 public static void ConfigureTransitions(
     TransitionHandlerProvider transitions,
     ITogglDatabase database,
     ITogglApi api,
     ITogglDataSource dataSource,
     IScheduler scheduler,
     ITimeService timeService,
     StateMachineEntryPoints entryPoints)
 {
     configurePullTransitions(transitions, database, api, dataSource, timeService, entryPoints.StartPullSync);
     configurePushTransitions(transitions, database, api, dataSource, scheduler, entryPoints.StartPushSync);
 }
Exemplo n.º 7
0
        private static void configurePullTransitions(
            TransitionHandlerProvider transitions,
            ITogglDatabase database,
            ITogglApi api,
            ITogglDataSource dataSource,
            ITimeService timeService,
            IScheduler scheduler,
            StateResult entryPoint,
            IObservable <Unit> delayCancellation)
        {
            var rnd         = new Random();
            var apiDelay    = new RetryDelayService(rnd);
            var statusDelay = new RetryDelayService(rnd);

            var fetchAllSince            = new FetchAllSinceState(database, api, timeService);
            var persistWorkspaces        = new PersistWorkspacesState(database.Workspaces, database.SinceParameters);
            var persistWorkspaceFeatures = new PersistWorkspacesFeaturesState(database.WorkspaceFeatures, database.SinceParameters);
            var persistUser        = new PersistUserState(database.User, database.SinceParameters);
            var persistTags        = new PersistTagsState(database.Tags, database.SinceParameters);
            var persistClients     = new PersistClientsState(database.Clients, database.SinceParameters);
            var persistPreferences = new PersistPreferencesState(dataSource.Preferences, database.SinceParameters);
            var persistProjects    = new PersistProjectsState(database.Projects, database.SinceParameters);
            var persistTimeEntries = new PersistTimeEntriesState(dataSource.TimeEntries, database.SinceParameters, timeService);
            var persistTasks       = new PersistTasksState(database.Tasks, database.SinceParameters);
            var checkServerStatus  = new CheckServerStatusState(api, scheduler, apiDelay, statusDelay, delayCancellation);
            var finished           = new ResetAPIDelayState(apiDelay);

            transitions.ConfigureTransition(entryPoint, fetchAllSince.Start);
            transitions.ConfigureTransition(fetchAllSince.FetchStarted, persistWorkspaces.Start);
            transitions.ConfigureTransition(persistWorkspaces.FinishedPersisting, persistUser.Start);
            transitions.ConfigureTransition(persistUser.FinishedPersisting, persistWorkspaceFeatures.Start);
            transitions.ConfigureTransition(persistWorkspaceFeatures.FinishedPersisting, persistPreferences.Start);
            transitions.ConfigureTransition(persistPreferences.FinishedPersisting, persistTags.Start);
            transitions.ConfigureTransition(persistTags.FinishedPersisting, persistClients.Start);
            transitions.ConfigureTransition(persistClients.FinishedPersisting, persistProjects.Start);
            transitions.ConfigureTransition(persistProjects.FinishedPersisting, persistTasks.Start);
            transitions.ConfigureTransition(persistTasks.FinishedPersisting, persistTimeEntries.Start);

            transitions.ConfigureTransition(persistWorkspaces.Failed, checkServerStatus.Start);
            transitions.ConfigureTransition(persistWorkspaceFeatures.Failed, checkServerStatus.Start);
            transitions.ConfigureTransition(persistPreferences.Failed, checkServerStatus.Start);
            transitions.ConfigureTransition(persistTags.Failed, checkServerStatus.Start);
            transitions.ConfigureTransition(persistClients.Failed, checkServerStatus.Start);
            transitions.ConfigureTransition(persistProjects.Failed, checkServerStatus.Start);
            transitions.ConfigureTransition(persistTasks.Failed, checkServerStatus.Start);
            transitions.ConfigureTransition(persistTimeEntries.Failed, checkServerStatus.Start);

            transitions.ConfigureTransition(checkServerStatus.Retry, checkServerStatus.Start);
            transitions.ConfigureTransition(checkServerStatus.ServerIsAvailable, finished.Start);
            transitions.ConfigureTransition(finished.Continue, fetchAllSince.Start);
        }
Exemplo n.º 8
0
        private static IStateResult configurePush <T>(
            TransitionHandlerProvider transitions,
            IStateResult entryPoint,
            BasePushState <T> push,
            PushOneEntityState <T> pushOne,
            BaseCreateEntityState <T> create,
            BaseUpdateEntityState <T> update,
            BaseDeleteEntityState <T> delete,
            BaseDeleteLocalEntityState <T> deleteLocal,
            TryResolveClientErrorState <T> tryResolveClientError,
            BaseUnsyncableEntityState <T> markUnsyncable,
            CheckServerStatusState checkServerStatus,
            ResetAPIDelayState finished)
            where T : class, IBaseModel, IDatabaseSyncable
        {
            transitions.ConfigureTransition(entryPoint, push.Start);
            transitions.ConfigureTransition(push.PushEntity, pushOne.Start);
            transitions.ConfigureTransition(pushOne.CreateEntity, create.Start);
            transitions.ConfigureTransition(pushOne.UpdateEntity, update.Start);
            transitions.ConfigureTransition(pushOne.DeleteEntity, delete.Start);
            transitions.ConfigureTransition(pushOne.DeleteEntityLocally, deleteLocal.Start);

            transitions.ConfigureTransition(create.ClientError, tryResolveClientError.Start);
            transitions.ConfigureTransition(update.ClientError, tryResolveClientError.Start);
            transitions.ConfigureTransition(delete.ClientError, tryResolveClientError.Start);

            transitions.ConfigureTransition(create.ServerError, checkServerStatus.Start);
            transitions.ConfigureTransition(update.ServerError, checkServerStatus.Start);
            transitions.ConfigureTransition(delete.ServerError, checkServerStatus.Start);

            transitions.ConfigureTransition(create.UnknownError, checkServerStatus.Start);
            transitions.ConfigureTransition(update.UnknownError, checkServerStatus.Start);
            transitions.ConfigureTransition(delete.UnknownError, checkServerStatus.Start);

            transitions.ConfigureTransition(tryResolveClientError.UnresolvedTooManyRequests, checkServerStatus.Start);
            transitions.ConfigureTransition(tryResolveClientError.Unresolved, markUnsyncable.Start);

            transitions.ConfigureTransition(checkServerStatus.Retry, checkServerStatus.Start);
            transitions.ConfigureTransition(checkServerStatus.ServerIsAvailable, push.Start);

            transitions.ConfigureTransition(create.CreatingFinished, finished.Start);
            transitions.ConfigureTransition(update.UpdatingSucceeded, finished.Start);
            transitions.ConfigureTransition(delete.DeletingFinished, finished.Start);
            transitions.ConfigureTransition(deleteLocal.Deleted, finished.Start);
            transitions.ConfigureTransition(deleteLocal.DeletingFailed, finished.Start);

            transitions.ConfigureTransition(finished.Continue, push.Start);

            return(push.NothingToPush);
        }
Exemplo n.º 9
0
        private static IStateResult configureCreateOnlyPush <TModel, TDatabase, TThreadsafe>(
            TransitionHandlerProvider transitions,
            IStateResult entryPoint,
            IDataSource <TThreadsafe, TDatabase> dataSource,
            ICreatingApiClient <TModel> creatingApi,
            Func <TModel, TThreadsafe> toClean,
            Func <TThreadsafe, string, TThreadsafe> toUnsyncable,
            ITogglApi api,
            IScheduler scheduler,
            IObservable <Unit> delayCancellation)
            where TModel : IIdentifiable, ILastChangedDatable
            where TDatabase : class, TModel, IDatabaseSyncable
            where TThreadsafe : class, TDatabase, IThreadSafeModel
        {
            var rnd         = new Random();
            var apiDelay    = new RetryDelayService(rnd);
            var statusDelay = new RetryDelayService(rnd);

            var push    = new PushState <TDatabase, TThreadsafe>(dataSource);
            var pushOne = new PushOneEntityState <TThreadsafe>();
            var create  = new CreateEntityState <TModel, TThreadsafe>(creatingApi, dataSource, toClean);
            var tryResolveClientError = new TryResolveClientErrorState <TThreadsafe>();
            var unsyncable            = new UnsyncableEntityState <TThreadsafe>(dataSource, toUnsyncable);
            var checkServerStatus     = new CheckServerStatusState(api, scheduler, apiDelay, statusDelay, delayCancellation);
            var finished = new ResetAPIDelayState(apiDelay);

            transitions.ConfigureTransition(entryPoint, push);
            transitions.ConfigureTransition(push.PushEntity, pushOne);
            transitions.ConfigureTransition(pushOne.CreateEntity, create);

            transitions.ConfigureTransition(pushOne.UpdateEntity, new InvalidTransitionState($"Updating is not supported for {typeof(TModel).Name} during Push sync."));
            transitions.ConfigureTransition(pushOne.DeleteEntity, new InvalidTransitionState($"Deleting is not supported for {typeof(TModel).Name} during Push sync."));
            transitions.ConfigureTransition(pushOne.DeleteEntityLocally, new InvalidTransitionState($"Deleting locally is not supported for {typeof(TModel).Name} during Push sync."));

            transitions.ConfigureTransition(create.ClientError, tryResolveClientError);
            transitions.ConfigureTransition(create.ServerError, checkServerStatus);
            transitions.ConfigureTransition(create.UnknownError, checkServerStatus);

            transitions.ConfigureTransition(tryResolveClientError.UnresolvedTooManyRequests, checkServerStatus);
            transitions.ConfigureTransition(tryResolveClientError.Unresolved, unsyncable);

            transitions.ConfigureTransition(checkServerStatus.Retry, checkServerStatus);
            transitions.ConfigureTransition(checkServerStatus.ServerIsAvailable, push);

            transitions.ConfigureTransition(create.CreatingFinished, finished);

            transitions.ConfigureTransition(finished.Continue, push);

            return(push.NothingToPush);
        }
Exemplo n.º 10
0
 public static void ConfigureTransitions(
     TransitionHandlerProvider transitions,
     ITogglDatabase database,
     ITogglApi api,
     ITogglDataSource dataSource,
     IRetryDelayService apiDelay,
     IScheduler scheduler,
     ITimeService timeService,
     StateMachineEntryPoints entryPoints,
     IObservable <Unit> delayCancellation)
 {
     configurePullTransitions(transitions, database, api, dataSource, timeService, scheduler, entryPoints.StartPullSync, delayCancellation);
     configurePushTransitions(transitions, database, api, dataSource, apiDelay, scheduler, entryPoints.StartPushSync, delayCancellation);
 }
Exemplo n.º 11
0
            protected void Reset()
            {
                var analyticsService     = Substitute.For <IAnalyticsService>();
                var lastTimeUsageStorage = Substitute.For <ILastTimeUsageStorage>();
                var timeService          = Substitute.For <ITimeService>();

                Queue        = new SyncStateQueue();
                Transitions  = new TransitionHandlerProvider();
                Scheduler    = new TestScheduler();
                StateMachine = new StateMachine(Transitions, Scheduler, Substitute.For <ISubject <Unit> >());
                EntryPoints  = new StateMachineEntryPoints();
                Orchestrator = new StateMachineOrchestrator(StateMachine, EntryPoints);
                SyncManager  = new SyncManager(Queue, Orchestrator, analyticsService, lastTimeUsageStorage, timeService);
            }
Exemplo n.º 12
0
        private static void configurePushTransitions(
            TransitionHandlerProvider transitions,
            ITogglDatabase database,
            ITogglApi api,
            ITogglDataSource dataSource,
            IScheduler scheduler,
            StateResult entryPoint,
            IObservable <Unit> delayCancellation)
        {
            var pushingUsersFinished    = configurePushTransitionsForUsers(transitions, database, api, scheduler, entryPoint, delayCancellation);
            var pushingTagsFinished     = configurePushTransitionsForTags(transitions, database, api, scheduler, pushingUsersFinished, delayCancellation);
            var pushingClientsFinished  = configurePushTransitionsForClients(transitions, database, api, scheduler, pushingTagsFinished, delayCancellation);
            var pushingProjectsFinished = configurePushTransitionsForProjects(transitions, database, api, scheduler, pushingClientsFinished, delayCancellation);

            configurePushTransitionsForTimeEntries(transitions, database, api, dataSource, scheduler, pushingProjectsFinished, delayCancellation);
        }
Exemplo n.º 13
0
        private static void configurePushTransitions(
            TransitionHandlerProvider transitions,
            ITogglApi api,
            ITogglDataSource dataSource,
            IRetryDelayService apiDelay,
            IScheduler scheduler,
            StateResult entryPoint,
            IObservable <Unit> delayCancellation)
        {
            var pushingUsersFinished       = configurePushSingleton(transitions, entryPoint, dataSource.User, api.User, User.Clean, User.Unsyncable, api, scheduler, delayCancellation);
            var pushingPreferencesFinished = configurePushSingleton(transitions, pushingUsersFinished, dataSource.Preferences, api.Preferences, Preferences.Clean, Preferences.Unsyncable, api, scheduler, delayCancellation);
            var pushingTagsFinished        = configureCreateOnlyPush(transitions, pushingPreferencesFinished, dataSource.Tags, api.Tags, Tag.Clean, Tag.Unsyncable, api, scheduler, delayCancellation);
            var pushingClientsFinished     = configureCreateOnlyPush(transitions, pushingTagsFinished, dataSource.Clients, api.Clients, Client.Clean, Client.Unsyncable, api, scheduler, delayCancellation);
            var pushingProjectsFinished    = configureCreateOnlyPush(transitions, pushingClientsFinished, dataSource.Projects, api.Projects, Project.Clean, Project.Unsyncable, api, scheduler, delayCancellation);

            configurePush(transitions, pushingProjectsFinished, dataSource.TimeEntries, api.TimeEntries, api.TimeEntries, api.TimeEntries, TimeEntry.Clean, TimeEntry.Unsyncable, api, apiDelay, scheduler, delayCancellation);
        }
Exemplo n.º 14
0
        public static ISyncManager CreateSyncManager(
            ITogglDatabase database,
            ITogglApi api,
            ITogglDataSource dataSource,
            ITimeService timeService,
            IScheduler scheduler)
        {
            var queue       = new SyncStateQueue();
            var entryPoints = new StateMachineEntryPoints();
            var transitions = new TransitionHandlerProvider();

            ConfigureTransitions(transitions, database, api, dataSource, scheduler, timeService, entryPoints);
            var stateMachine = new StateMachine(transitions, scheduler);
            var orchestrator = new StateMachineOrchestrator(stateMachine, entryPoints);

            return(new SyncManager(queue, orchestrator));
        }
Exemplo n.º 15
0
        public static ISyncManager CreateSyncManager(
            ITogglDatabase database,
            ITogglApi api,
            ITogglDataSource dataSource,
            ITimeService timeService,
            IScheduler scheduler)
        {
            var queue                       = new SyncStateQueue();
            var entryPoints                 = new StateMachineEntryPoints();
            var transitions                 = new TransitionHandlerProvider();
            var delayCancellation           = new Subject <Unit>();
            var delayCancellationObservable = delayCancellation.AsObservable().Replay();

            ConfigureTransitions(transitions, database, api, dataSource, scheduler, timeService, entryPoints, delayCancellationObservable);
            var stateMachine = new StateMachine(transitions, scheduler, delayCancellation);
            var orchestrator = new StateMachineOrchestrator(stateMachine, entryPoints);

            return(new SyncManager(queue, orchestrator));
        }
        public static ISyncManager CreateSyncManager(
            ITogglDatabase database,
            ITogglApi api,
            ITogglDataSource dataSource,
            ITimeService timeService,
            IAnalyticsService analyticsService,
            ILastTimeUsageStorage lastTimeUsageStorage,
            IScheduler scheduler,
            IAutomaticSyncingService automaticSyncingService)
        {
            var queue       = new SyncStateQueue();
            var entryPoints = new StateMachineEntryPoints();
            var transitions = new TransitionHandlerProvider(analyticsService);

            ConfigureTransitions(transitions, database, api, dataSource, scheduler, timeService, analyticsService, lastTimeUsageStorage, entryPoints, queue);
            var stateMachine = new StateMachine(transitions, scheduler);
            var orchestrator = new StateMachineOrchestrator(stateMachine, entryPoints);

            return(new SyncManager(queue, orchestrator, analyticsService, lastTimeUsageStorage, timeService, automaticSyncingService));
        }
Exemplo n.º 17
0
        private static IStateResult configurePushTransitionsForProjects(
            TransitionHandlerProvider transitions,
            ITogglDatabase database,
            ITogglApi api,
            IScheduler scheduler,
            IStateResult entryPoint,
            IObservable <Unit> delayCancellation)
        {
            var rnd         = new Random();
            var apiDelay    = new RetryDelayService(rnd);
            var statusDelay = new RetryDelayService(rnd);

            var push              = new PushProjectsState(database.Projects);
            var pushOne           = new PushOneEntityState <IDatabaseProject>();
            var create            = new CreateProjectState(api, database.Projects);
            var unsyncable        = new UnsyncableProjectState(database.Projects);
            var checkServerStatus = new CheckServerStatusState(api, scheduler, apiDelay, statusDelay, delayCancellation);
            var finished          = new ResetAPIDelayState(apiDelay);

            return(configureCreateOnlyPush(transitions, entryPoint, push, pushOne, create, unsyncable, checkServerStatus, finished));
        }
Exemplo n.º 18
0
        private static IStateResult configurePushTransitionsForUsers(
            TransitionHandlerProvider transitions,
            ITogglDatabase database,
            ITogglApi api,
            IScheduler scheduler,
            IStateResult entryPoint,
            IObservable <Unit> delayCancellation)
        {
            var rnd         = new Random();
            var apiDelay    = new RetryDelayService(rnd);
            var statusDelay = new RetryDelayService(rnd);

            var push    = new PushUsersState(database.User);
            var pushOne = new PushOneEntityState <IDatabaseUser>();
            var update  = new UpdateUserState(api, database.User);
            var tryResolveClientError = new TryResolveClientErrorState <IDatabaseUser>();
            var unsyncable            = new UnsyncableUserState(database.User);
            var checkServerStatus     = new CheckServerStatusState(api, scheduler, apiDelay, statusDelay, delayCancellation);
            var finished = new ResetAPIDelayState(apiDelay);

            return(configureUpdateOnlyPush(transitions, entryPoint, push, pushOne, update, tryResolveClientError, unsyncable, checkServerStatus, finished));
        }
        public static ISyncManager CreateSyncManager(
            ITogglDatabase database,
            ITogglApi api,
            ITogglDataSource dataSource,
            ITimeService timeService,
            IAnalyticsService analyticsService,
            ILastTimeUsageStorage lastTimeUsageStorage,
            TimeSpan?retryLimit,
            IScheduler scheduler)
        {
            var random                      = new Random();
            var queue                       = new SyncStateQueue();
            var entryPoints                 = new StateMachineEntryPoints();
            var transitions                 = new TransitionHandlerProvider();
            var apiDelay                    = new RetryDelayService(random, retryLimit);
            var delayCancellation           = new Subject <Unit>();
            var delayCancellationObservable = delayCancellation.AsObservable().Replay();

            ConfigureTransitions(transitions, database, api, dataSource, apiDelay, scheduler, timeService, analyticsService, entryPoints, delayCancellationObservable);
            var stateMachine = new StateMachine(transitions, scheduler, delayCancellation);
            var orchestrator = new StateMachineOrchestrator(stateMachine, entryPoints);

            return(new SyncManager(queue, orchestrator, analyticsService, lastTimeUsageStorage, timeService));
        }
Exemplo n.º 20
0
        private static void configurePullTransitions(
            TransitionHandlerProvider transitions,
            ITogglDatabase database,
            ITogglApi api,
            ITogglDataSource dataSource,
            ITimeService timeService,
            IAnalyticsService analyticsService,
            IScheduler scheduler,
            StateResult entryPoint,
            IObservable <Unit> delayCancellation)
        {
            var rnd         = new Random();
            var apiDelay    = new RetryDelayService(rnd);
            var statusDelay = new RetryDelayService(rnd);

            var fetchAllSince = new FetchAllSinceState(database, api, timeService);

            var persistWorkspaces =
                new PersistListState <IWorkspace, IDatabaseWorkspace, IThreadSafeWorkspace>(dataSource.Workspaces, Workspace.Clean)
                .UpdateSince <IWorkspace, IDatabaseWorkspace>(database.SinceParameters)
                .ThrowNoWorkspaceExceptionIfNeeded()
                .CatchApiExceptions();

            var persistWorkspaceFeatures =
                new PersistListState <IWorkspaceFeatureCollection, IDatabaseWorkspaceFeatureCollection, IThreadSafeWorkspaceFeatureCollection>(
                    dataSource.WorkspaceFeatures, WorkspaceFeatureCollection.From)
                .CatchApiExceptions();

            var persistUser =
                new PersistSingletonState <IUser, IDatabaseUser, IThreadSafeUser>(dataSource.User, User.Clean)
                .CatchApiExceptions();

            var persistTags =
                new PersistListState <ITag, IDatabaseTag, IThreadSafeTag>(dataSource.Tags, Tag.Clean)
                .UpdateSince <ITag, IDatabaseTag>(database.SinceParameters)
                .CatchApiExceptions();

            var persistClients =
                new PersistListState <IClient, IDatabaseClient, IThreadSafeClient>(dataSource.Clients, Client.Clean)
                .UpdateSince <IClient, IDatabaseClient>(database.SinceParameters)
                .CatchApiExceptions();

            var persistPreferences =
                new PersistSingletonState <IPreferences, IDatabasePreferences, IThreadSafePreferences>(dataSource.Preferences, Preferences.Clean)
                .CatchApiExceptions();

            var persistProjects =
                new PersistListState <IProject, IDatabaseProject, IThreadSafeProject>(dataSource.Projects, Project.Clean)
                .UpdateSince <IProject, IDatabaseProject>(database.SinceParameters)
                .CatchApiExceptions();

            var createGhostProjects = new CreateGhostProjectsState(dataSource.Projects, analyticsService).CatchApiExceptions();

            var persistTimeEntries =
                new PersistListState <ITimeEntry, IDatabaseTimeEntry, IThreadSafeTimeEntry>(dataSource.TimeEntries, TimeEntry.Clean)
                .UpdateSince <ITimeEntry, IDatabaseTimeEntry>(database.SinceParameters)
                .CatchApiExceptions();

            var persistTasks =
                new PersistListState <ITask, IDatabaseTask, IThreadSafeTask>(dataSource.Tasks, Task.Clean)
                .UpdateSince <ITask, IDatabaseTask>(database.SinceParameters)
                .CatchApiExceptions();

            var refetchInaccessibleProjects =
                new TryFetchInaccessibleProjectsState(dataSource.Projects, timeService, api.Projects)
                .CatchApiExceptions();

            var checkServerStatus = new CheckServerStatusState(api, scheduler, apiDelay, statusDelay, delayCancellation);

            var finished           = new ResetAPIDelayState(apiDelay);
            var deleteOlderEntries = new DeleteOldEntriesState(timeService, dataSource.TimeEntries);
            var deleteNonReferencedGhostProjects = new DeleteNonReferencedProjectGhostsState(dataSource.Projects, dataSource.TimeEntries);

            transitions.ConfigureTransition(entryPoint, fetchAllSince);
            transitions.ConfigureTransition(fetchAllSince.FetchStarted, persistWorkspaces);
            transitions.ConfigureTransition(persistWorkspaces.UnsafeState.FinishedPersisting, persistUser);
            transitions.ConfigureTransition(persistUser.UnsafeState.FinishedPersisting, persistWorkspaceFeatures);
            transitions.ConfigureTransition(persistWorkspaceFeatures.UnsafeState.FinishedPersisting, persistPreferences);
            transitions.ConfigureTransition(persistPreferences.UnsafeState.FinishedPersisting, persistTags);
            transitions.ConfigureTransition(persistTags.UnsafeState.FinishedPersisting, persistClients);
            transitions.ConfigureTransition(persistClients.UnsafeState.FinishedPersisting, persistProjects);
            transitions.ConfigureTransition(persistProjects.UnsafeState.FinishedPersisting, persistTasks);
            transitions.ConfigureTransition(persistTasks.UnsafeState.FinishedPersisting, createGhostProjects);
            transitions.ConfigureTransition(createGhostProjects.UnsafeState.FinishedPersisting, persistTimeEntries);
            transitions.ConfigureTransition(persistTimeEntries.UnsafeState.FinishedPersisting, refetchInaccessibleProjects);
            transitions.ConfigureTransition(refetchInaccessibleProjects.UnsafeState.FetchNext, refetchInaccessibleProjects);

            transitions.ConfigureTransition(refetchInaccessibleProjects.UnsafeState.FinishedPersisting, deleteOlderEntries);
            transitions.ConfigureTransition(deleteOlderEntries.FinishedDeleting, deleteNonReferencedGhostProjects);

            transitions.ConfigureTransition(persistWorkspaces.Failed, checkServerStatus);
            transitions.ConfigureTransition(persistUser.Failed, checkServerStatus);
            transitions.ConfigureTransition(persistWorkspaceFeatures.Failed, checkServerStatus);
            transitions.ConfigureTransition(persistPreferences.Failed, checkServerStatus);
            transitions.ConfigureTransition(persistTags.Failed, checkServerStatus);
            transitions.ConfigureTransition(persistClients.Failed, checkServerStatus);
            transitions.ConfigureTransition(persistProjects.Failed, checkServerStatus);
            transitions.ConfigureTransition(persistTasks.Failed, checkServerStatus);
            transitions.ConfigureTransition(createGhostProjects.Failed, checkServerStatus);
            transitions.ConfigureTransition(persistTimeEntries.Failed, checkServerStatus);
            transitions.ConfigureTransition(refetchInaccessibleProjects.Failed, checkServerStatus);

            transitions.ConfigureTransition(checkServerStatus.Retry, checkServerStatus);
            transitions.ConfigureTransition(checkServerStatus.ServerIsAvailable, finished);
            transitions.ConfigureTransition(finished.Continue, fetchAllSince);
        }
Exemplo n.º 21
0
        private static IStateResult configurePush <TModel, TDatabase, TThreadsafe>(
            TransitionHandlerProvider transitions,
            IStateResult entryPoint,
            IDataSource <TThreadsafe, TDatabase> dataSource,
            ICreatingApiClient <TModel> creatingApi,
            IUpdatingApiClient <TModel> updatingApi,
            IDeletingApiClient <TModel> deletingApi,
            Func <TModel, TThreadsafe> toClean,
            Func <TThreadsafe, string, TThreadsafe> toUnsyncable,
            ITogglApi api,
            IRetryDelayService apiDelay,
            IScheduler scheduler,
            IObservable <Unit> delayCancellation)
            where TModel : class, IIdentifiable, ILastChangedDatable
            where TDatabase : class, TModel, IDatabaseSyncable
            where TThreadsafe : class, TDatabase, IThreadSafeModel
        {
            var rnd         = new Random();
            var statusDelay = new RetryDelayService(rnd);

            var push                  = new PushState <TDatabase, TThreadsafe>(dataSource);
            var pushOne               = new PushOneEntityState <TThreadsafe>();
            var create                = new CreateEntityState <TModel, TThreadsafe>(creatingApi, dataSource, toClean);
            var update                = new UpdateEntityState <TModel, TThreadsafe>(updatingApi, dataSource, toClean);
            var delete                = new DeleteEntityState <TModel, TDatabase, TThreadsafe>(deletingApi, dataSource);
            var deleteLocal           = new DeleteLocalEntityState <TDatabase, TThreadsafe>(dataSource);
            var tryResolveClientError = new TryResolveClientErrorState <TThreadsafe>();
            var unsyncable            = new UnsyncableEntityState <TThreadsafe>(dataSource, toUnsyncable);
            var checkServerStatus     = new CheckServerStatusState(api, scheduler, apiDelay, statusDelay, delayCancellation);
            var finished              = new ResetAPIDelayState(apiDelay);

            transitions.ConfigureTransition(entryPoint, push.Start);
            transitions.ConfigureTransition(push.PushEntity, pushOne.Start);
            transitions.ConfigureTransition(pushOne.CreateEntity, create.Start);
            transitions.ConfigureTransition(pushOne.UpdateEntity, update.Start);
            transitions.ConfigureTransition(pushOne.DeleteEntity, delete.Start);
            transitions.ConfigureTransition(pushOne.DeleteEntityLocally, deleteLocal.Start);

            transitions.ConfigureTransition(create.ClientError, tryResolveClientError.Start);
            transitions.ConfigureTransition(update.ClientError, tryResolveClientError.Start);
            transitions.ConfigureTransition(delete.ClientError, tryResolveClientError.Start);

            transitions.ConfigureTransition(create.ServerError, checkServerStatus.Start);
            transitions.ConfigureTransition(update.ServerError, checkServerStatus.Start);
            transitions.ConfigureTransition(delete.ServerError, checkServerStatus.Start);

            transitions.ConfigureTransition(create.UnknownError, checkServerStatus.Start);
            transitions.ConfigureTransition(update.UnknownError, checkServerStatus.Start);
            transitions.ConfigureTransition(delete.UnknownError, checkServerStatus.Start);

            transitions.ConfigureTransition(tryResolveClientError.UnresolvedTooManyRequests, checkServerStatus.Start);
            transitions.ConfigureTransition(tryResolveClientError.Unresolved, unsyncable.Start);

            transitions.ConfigureTransition(checkServerStatus.Retry, checkServerStatus.Start);
            transitions.ConfigureTransition(checkServerStatus.ServerIsAvailable, push.Start);

            transitions.ConfigureTransition(create.CreatingFinished, finished.Start);
            transitions.ConfigureTransition(update.UpdatingSucceeded, finished.Start);
            transitions.ConfigureTransition(delete.DeletingFinished, finished.Start);
            transitions.ConfigureTransition(deleteLocal.Deleted, finished.Start);
            transitions.ConfigureTransition(deleteLocal.DeletingFailed, finished.Start);

            transitions.ConfigureTransition(finished.Continue, push.Start);

            return(push.NothingToPush);
        }
Exemplo n.º 22
0
 public ConfigureTransitionMethodTests()
 {
     AnalyticsService = Substitute.For <IAnalyticsService>();
     Provider         = new TransitionHandlerProvider(AnalyticsService);
 }
Exemplo n.º 23
0
 public TheGetTransitionHandlerMethod()
 {
     analyticsService = Substitute.For <IAnalyticsService>();
     provider         = new TransitionHandlerProvider(analyticsService);
 }