Beispiel #1
0
        public async Task <DocumentHeaderResponse> Store(CouchConveyEntry <T> entry, string revision)
        {
            if (this.Client == null)
            {
                Logger.ErrorFormat("CouchDb client is not ready to process: {0}", entry);
                throw new InvalidOperationException("CouchDb client is not ready.");
            }

            var res = await TryPut(entry, revision);

            if (res != null)
            {
                return(res);
            }

            if (entry.Overwrite)
            {
                while (res == null)
                {
                    var head = await this.Client.Documents.HeadAsync(entry.Id);

                    res = await TryPut(entry, head.Rev);                      // We still have a chance to get conflict by timing
                }
            }
            return(res);
        }
Beispiel #2
0
        public async Task <DocumentHeaderResponse> TryPut(CouchConveyEntry <T> entry, string revision)
        {
            try
            {
                DocumentHeaderResponse header = null;
                if (entry.Json == null && entry.Entity == null)
                {
                    header = await this.Client.Documents.DeleteAsync(entry.Id, revision);
                }
                else if (revision != null)
                {
                    header = await this.Client.Documents.PutAsync(entry.Id, revision, entry.Json);
                }
                else
                {
                    header = await this.Client.Documents.PutAsync(entry.Id, entry.Json);
                }

                if (header.StatusCode == System.Net.HttpStatusCode.Conflict && entry.Overwrite)
                {
                    return(null);                     // In this case, we will retry this outside so it's expected exception.
                }
                return(header);
            }
            catch (MyCouchResponseException ex)
            {
                Logger.DebugFormat("Error during put document {0}:{1} by {2}", entry.Id, revision, ex);
                if (ex.HttpStatus == System.Net.HttpStatusCode.Conflict && entry.Overwrite)
                {
                    return(null);                     // In this case, we will retry this outside so it's expected exception.
                }
                throw ex;
            }
        }
        public CouchTaskSerializeContext <T> GetContextFor(CouchConveyEntry <T> entry)
        {
            CouchTaskSerializeContext <T> context;

            if (_working_map.TryGetValue(entry.Id, out context))
            {
                return(context);
            }

            return(_working_map.GetOrAdd(entry.Id, new CouchTaskSerializeContext <T>(entry.Id)));
        }
Beispiel #4
0
        protected override async Task <bool> Process(CouchConveyEntry <T> entry)
        {
            try
            {
                var header = await Store(entry, null);

                if (header != null && header.IsSuccess)
                {
                    entry.Handler.OnStored(entry.Id, header.Rev, entry.Entity);
                    return(true);
                }

                throw new MyCouchResponseException(header);
            }
            catch (Exception ex)
            {
                entry.Handler.OnFailed(entry.Id, entry.Entity, ex);
                return(false);
            }
        }
 internal void Processed(CouchConveyEntry <T> t)
 {
     ProcessedQueue.Enqueue(t);
     ProcessedContext.Enqueue(Tuple.Create(this._lock_seq, this._lock_id));
 }
        // FIXME: This weird method extraction is for resolve synchronization problem between `this.WorkingQueue.TryTake(out entry)`
        //        and `context.WaitingQueue.Enqueue(entry);`. But this is too rough. Let me polish this later.
        protected override async Task <bool> TakeOneAndProcess()
        {
            CouchConveyEntry <T>          entry   = null;
            CouchTaskSerializeContext <T> context = null;

            lock (this._task_serializer)
            {
                if (this.WorkingQueue.TryTake(out entry))
                {
                    context = _task_serializer.GetContextFor(entry);
                    context.WaitingQueue.Enqueue(entry);
                }
                else
                {
                    return(false);
                }
            }

            if (entry == null || context == null)
            {
                Logger.Error("Invalid queue handling", new InvalidOperationException());
                return(false);
            }

            int?lock_id = context.TryStartWork();

            if (null == lock_id)
            {
                return(true);
            }
            try
            {
                CouchConveyEntry <T> t;
                while (context.WaitingQueue.TryDequeue(out t))
                {
                    context.Processed(t);
                    try
                    {
                        var header = await Store(t, context.Rev);

                        if (header != null && header.IsSuccess)
                        {
                            t.Handler.OnStored(t.Id, header.Rev, t.Entity);
                            context.Rev = header.Rev;
                        }
                        else
                        {
                            throw new MyCouchResponseException(header);
                        }
                    }
                    catch (Exception ex)
                    {
                        t.Handler.OnFailed(t.Id, t.Entity, ex);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error(new object[] { "Dispatcher throws uncaught exception.", entry }, ex);
            }
            finally
            {
                context.EndWork(lock_id ?? 0);
            }
            return(true);
        }