Beispiel #1
0
        async void _finish(XFlowState state)
        {
            if (!_persistOnComplete)
            {
                if (_state.Contains(state))
                {
                    _state.Remove(state);
                }
                await _save();

                return;
            }

            state.IsComplete = true;

            Debug.WriteLine("Completed State Flow with {0}: {1}", state.PreviousStageSuccess, state);

            if (state.PreviousStageSuccess)
            {
                state.State        = XFlowStates.Success;
                state.IsSuccessful = true;
                state.Timestamp    = DateTime.UtcNow;
                await _save();

                return;
            }

            state.State        = XFlowStates.Fail;
            state.IsSuccessful = false;
            state.Timestamp    = DateTime.UtcNow;

            await _save();
        }
Beispiel #2
0
        bool _moveNextStage(XFlowState state)
        {
            if (state.StageId == null)
            {
                var firstStage = _stages.First();
                state.StageId = firstStage.StageId;
                return(true);
            }

            var stage = _getStage(state);

            var index = _stages.IndexOf(stage);

            var newIndex = index + 1;

            if (newIndex >= _stages.Count)
            {
                //this is the last stage, so return false;
                return(false);
            }

            var newStage = _stages[newIndex];

            state.StageId      = newStage.StageId;
            state.FailureCount = 0;
            return(true);
        }
Beispiel #3
0
        async Task _failResult(XFlowState state)
        {
            state.PreviousStageSuccess = false;

            var stage = _getStage(state);

            state.Text = stage.FailText;

            if (stage.Retries > 0)
            {
                if (state.FailureCount <= stage.Retries)
                {
                    //let's retry
                    state.FailureCount++;
                    state.State     = XFlowStates.WaitingForRetry;
                    state.Timestamp = DateTime.UtcNow;
                    await _save();

                    _cancelProcessWait();
                    return;
                }
            }

            await stage.Fail(state.ItemId);

            Debug.WriteLine("Stage Failed [{0}] {1} - {2}",
                            state.ItemId,
                            state.PreviousStageResult != null ? state.PreviousStageResult.ExtraText : "No Extra Text",
                            state.PreviousStageResult != null ? state.PreviousStageResult.Exception : "No Exception");
            Debug.WriteLine("Failure stage: {0}", stage.ProcessingText);
            _finish(state);
        }
Beispiel #4
0
        public async Task <XFlowState> Start(Guid id)
        {
            if (!IsComplete)
            {
                throw new InvalidOperationException("Cannot start flows until Complete() is called");
            }

            var flowState = new XFlowState
            {
                Id         = Guid.NewGuid(),
                ItemId     = id,
                State      = XFlowStates.WaitingForNextStage,
                StageId    = null,
                Timestamp  = DateTime.UtcNow,
                ParentFlow = this
            };

            using (var l = await _stateLock.LockAsync())
            {
                var existing = _state.FirstOrDefault(_ => _.ItemId == id);

                if (existing != null)
                {
                    //if it's not failed or completed then clear it and start gain.
                    if (existing.State != XFlowStates.Fail && existing.State != XFlowStates.Success)
                    {
                        return(null);
                    }

                    _state.Remove(existing);
                }

                _state.Add(flowState);
            }

            await _save();

            _cancelProcessWait();

            return(flowState);
        }
Beispiel #5
0
        async Task _successResult(XFlowState state)
        {
            //state.Text = "";
            state.PreviousStageSuccess = true;

            if (state.PreviousStageResult != null && state.PreviousStageResult.CompleteNow)
            {
                //the result has asked for the workflow to complete early
                //this could be because the rest isn't needed, e.g. an entity was detected
                //locally so there is no need to get it form the server.
                _finish(state);
                return;
            }

            state.State     = XFlowStates.WaitingForNextStage;
            state.Timestamp = DateTime.UtcNow;

            await _save();

            _cancelProcessWait();
        }
Beispiel #6
0
        XStage _getStage(XFlowState state)
        {
            var stage = _stages.First(_ => _.StageId == state.StageId);

            return(stage);
        }
Beispiel #7
0
        Task _runStage(XFlowState state)
        {
            if (state.State != XFlowStates.WaitingForNetwork && state.State != XFlowStates.WaitingForRetry &&
                state.State != XFlowStates.WaitingToStart)
            {
                return(null);
            }

            if (_inProgressStates.Contains(state))
            {
                return(null);
            }


            var t = Task.Run(async() =>
            {
                var stage = _getStage(state);

                if (stage.RequiresNetwork && !_networkStatus.QuickNetworkCheck())
                {
                    state.State = XFlowStates.WaitingForNetwork;
                    await Task.Yield();
                    return;
                }

                state.Text = stage.ProcessingText;

                state.State     = XFlowStates.InProgress;
                state.Timestamp = DateTime.UtcNow;


                if (stage.IsDisconnectedProcess)
                {
                    state.State = XFlowStates.DisconnectedProcessing;
                    await _save();
                    Debug.WriteLine("Stopping flow for disconnected state, will resume when asked. {0}", state);
                    return;
                }

                await _save();

                XStageResult failResult = null;

                try
                {
                    if (_inProgressStates.Contains(state))
                    {
                        return;
                    }

                    _inProgressStates.Add(state);

                    var result = await stage.Function(state.ItemId);

                    if (result.Id != Guid.Empty)
                    {
                        state.ItemId = result.Id;
                    }

                    state.PreviousStageResult = result;

                    _inProgressStates.Remove(state);

                    if (!result.IsSuccess)
                    {
                        await _failResult(state);
                    }
                    else
                    {
                        await _successResult(state);
                    }
                }
                catch (Exception ex)
                {
                    _inProgressStates.Remove(state);
                    failResult = new XStageResult(false, state.ItemId, null, exception: ex.ToString());
                }

                if (failResult != null)
                {
                    state.PreviousStageResult = failResult;

                    var stateString = _entitySerialiser.Serialise(state);

                    Debug.WriteLine("Caught exception process: {0}", stateString);

                    await _failResult(state);
                }

                _cancelProcessWait();
            });

            return(t);
        }
Beispiel #8
0
        bool _moveNextStage(XFlowState state)
        {
            if (state.StageId == null)
            {
                var firstStage = _stages.First();
                state.StageId = firstStage.StageId;
                return true;
            }

            var stage = _getStage(state);

            var index = _stages.IndexOf(stage);

            var newIndex = index + 1;

            if (newIndex >= _stages.Count)
            {
                //this is the last stage, so return false;
                return false;
            }

            var newStage = _stages[newIndex];

            state.StageId = newStage.StageId;
            state.FailureCount = 0;
            return true;
        }
Beispiel #9
0
        XStage _getStage(XFlowState state)
        {
            var stage = _stages.First(_ => _.StageId == state.StageId);

            return stage;
        }
Beispiel #10
0
        async void _finish(XFlowState state)
        {
            if (!_persistOnComplete)
            {
                if (_state.Contains(state))
                {
                    _state.Remove(state);
                }
                await _save();
                return;
            }

            state.IsComplete = true;

            Debug.WriteLine("Completed State Flow with {0}: {1}", state.PreviousStageSuccess, state);

            if (state.PreviousStageSuccess)
            {
                state.State = XFlowStates.Success;
                state.IsSuccessful = true;
                state.Timestamp = DateTime.UtcNow;
                await _save();
                return;
            }

            state.State = XFlowStates.Fail;
            state.IsSuccessful = false;
            state.Timestamp = DateTime.UtcNow;

            await _save();
        }
Beispiel #11
0
        async Task _successResult(XFlowState state)
        {
            //state.Text = "";
            state.PreviousStageSuccess = true;

            if (state.PreviousStageResult != null && state.PreviousStageResult.CompleteNow)
            {
                //the result has asked for the workflow to complete early
                //this could be because the rest isn't needed, e.g. an entity was detected
                //locally so there is no need to get it form the server. 
                _finish(state);
                return;
            }

            state.State = XFlowStates.WaitingForNextStage;
            state.Timestamp = DateTime.UtcNow;

            await _save();

            _cancelProcessWait();
        }
Beispiel #12
0
        async Task _failResult(XFlowState state)
        {
            state.PreviousStageSuccess = false;

            var stage = _getStage(state);

            state.Text = stage.FailText;

            if (stage.Retries > 0)
            {
                if (state.FailureCount <= stage.Retries)
                {
                    //let's retry
                    state.FailureCount++;
                    state.State = XFlowStates.WaitingForRetry;
                    state.Timestamp = DateTime.UtcNow;
                    await _save();
                    _cancelProcessWait();
                    return;
                }
            }

            await stage.Fail(state.ItemId);
            Debug.WriteLine("Stage Failed [{0}] {1} - {2}",
                state.ItemId,
                state.PreviousStageResult != null ? state.PreviousStageResult.ExtraText : "No Extra Text",
                state.PreviousStageResult != null ? state.PreviousStageResult.Exception : "No Exception");
            Debug.WriteLine("Failure stage: {0}", stage.ProcessingText);
            _finish(state);
        }
Beispiel #13
0
        Task _runStage(XFlowState state)
        {
            if (state.State != XFlowStates.WaitingForNetwork && state.State != XFlowStates.WaitingForRetry &&
                state.State != XFlowStates.WaitingToStart)
            {
                return null;
            }

            if (_inProgressStates.Contains(state))
            {
                return null;
            }
                

            var t = Task.Run(async () =>
            {
                var stage = _getStage(state);

                if (stage.RequiresNetwork && !_networkStatus.QuickNetworkCheck())
                {
                    state.State = XFlowStates.WaitingForNetwork;
                    await Task.Yield();
                    return;
                }

                state.Text = stage.ProcessingText;

                state.State = XFlowStates.InProgress;
                state.Timestamp = DateTime.UtcNow;


                if (stage.IsDisconnectedProcess)
                {
                    state.State = XFlowStates.DisconnectedProcessing;
                    await _save();
                    Debug.WriteLine("Stopping flow for disconnected state, will resume when asked. {0}", state);
                    return;
                }

                await _save();

                XStageResult failResult = null;

                try
                {
                    if (_inProgressStates.Contains(state))
                    {
                        return;
                    }

                    _inProgressStates.Add(state);
                    
                    var result = await stage.Function(state.ItemId);
                    
                    if (result.Id != Guid.Empty)
                    {
                        state.ItemId = result.Id;
                    }

                    state.PreviousStageResult = result;

                    _inProgressStates.Remove(state);

                    if (!result.IsSuccess)
                    {
                        await _failResult(state);
                    }
                    else
                    {
                        await _successResult(state);
                    }

                }
                catch (Exception ex)
                {
                    _inProgressStates.Remove(state);
                    failResult = new XStageResult(false, state.ItemId, null, exception: ex.ToString());
                }

                if (failResult != null)
                {
                    state.PreviousStageResult = failResult;

                    var stateString = _entitySerialiser.Serialise(state);

                    Debug.WriteLine("Caught exception process: {0}", stateString);

                    await _failResult(state);
                }
               
                _cancelProcessWait();
            });

            return t;
        }
Beispiel #14
0
        public async Task<XFlowState> Start(Guid id)
        {
            if (!IsComplete)
            {
                throw new InvalidOperationException("Cannot start flows until Complete() is called");
            }

            var flowState = new XFlowState
            {
                Id = Guid.NewGuid(),
                ItemId = id,
                State = XFlowStates.WaitingForNextStage,
                StageId = null,
                Timestamp = DateTime.UtcNow,
                ParentFlow = this
            };

            using (var l = await _stateLock.LockAsync())
            {
                var existing = _state.FirstOrDefault(_ => _.ItemId == id);

                if (existing != null)
                {
                    //if it's not failed or completed then clear it and start gain. 
                    if (existing.State != XFlowStates.Fail && existing.State != XFlowStates.Success)
                    {
                        return null;
                    }

                    _state.Remove(existing);
                }

                _state.Add(flowState);
            }

            await _save();

            _cancelProcessWait();

            return flowState;

        }