示例#1
0
        public override TodoFrame FetchLatestCorrelated(TodoQueue queue, string correlationKey, DateTime utcStartingFrom)
        {
            if (Disposed || queue == null || correlationKey == null)
            {
                return(new TodoFrame());
            }

            var collection = m_Database[queue.Name];


            var query = new Query(
                @"{
         '$query': { cky: '$$cky', sd: {'$gt': '$$utcFrom'} },
         '$orderby': { sd: -1}
        }",
                true, new TemplateArg(new BSONStringElement("cky", correlationKey)),
                new TemplateArg(new BSONDateTimeElement("utcFrom", utcStartingFrom)));

            var doc = collection.FindOne(query);

            if (doc == null)
            {
                return(new TodoFrame());
            }

            var frame = toFrame(queue, doc);

            return(frame);
        }
示例#2
0
 private void put(TodoQueue queue, TodoFrame todo, object transaction = null, bool leak = false)
 {
     try
     {
         m_QueueStore.Put(queue, todo, transaction);
         if (InstrumentationEnabled)
         {
             m_stat_PutTodoCount.IncrementLong(ALL);
             m_stat_PutTodoCount.IncrementLong(queue.Name);
         }
     }
     catch (Exception e)
     {
         var from = "put('{0}')".Args(queue.Name);
         WriteLog(MessageType.Critical, from, "{0} Leaked: {1}".Args(todo, e.ToMessageWithType()), e);
         if (InstrumentationEnabled)
         {
             m_stat_QueueOperationErrorCount.IncrementLong(ALL);
             m_stat_QueueOperationErrorCount.IncrementLong(from);
         }
         if (leak)
         {
             throw;
         }
     }
 }
                                              private bool checkDups(TodoQueue queue, TodoFrame todo)
                                              {
                                                  var mode = queue.DuplicationHandling;

                                                  if (mode == TodoQueue.DuplicationHandlingMode.NotDetected)
                                                  {
                                                      return(false);      //never a duplicate
                                                  }
                                                  var result = checkDupsInMemory(todo);

                                                  if (result || mode == TodoQueue.DuplicationHandlingMode.HostFastDetection)
                                                  {
                                                      return(result);
                                                  }

                                                  result = checkDupsInQueueStore(queue, todo);

                                                  if (result || mode == TodoQueue.DuplicationHandlingMode.HostAccurateDetection)
                                                  {
                                                      return(result);
                                                  }

                                                  result = checkDupsInHostset(queue, todo);

                                                  return(result);
                                              }
示例#4
0
        private TodoFrame toFrame(TodoQueue queue, BSONDocument doc)
        {
            try
            {
                var result = new TodoFrame();

                result.ID   = DataDocConverter.GDID_BSONtoCLR(doc[Query._ID] as BSONBinaryElement);
                result.Type = Guid.Parse(((BSONStringElement)doc[FLD_TODO_TYPE]).Value);
                result.CreateTimestampUTC = ((BSONDateTimeElement)doc[FLD_TODO_CREATETIMESTAMP]).Value;

                result.ShardingKey = elmStr(doc[FLD_TODO_SHARDINGKEY]);
                result.ParallelKey = elmStr(doc[FLD_TODO_PARALLELKEY]);

                result.Priority  = ((BSONInt32Element)doc[FLD_TODO_PRIORITY]).Value;
                result.StartDate = ((BSONDateTimeElement)doc[FLD_TODO_STARTDATE]).Value;

                result.CorrelationKey = elmStr(doc[FLD_TODO_CORRELATIONKEY]);

                result.State = ((BSONInt32Element)doc[FLD_TODO_STATE]).Value;
                result.Tries = ((BSONInt32Element)doc[FLD_TODO_TRIES]).Value;

                result.Serializer = ((BSONInt32Element)doc[FLD_TODO_SERIALIZER]).Value;
                result.Content    = elmBin(doc[FLD_TODO_CONTENT]);

                return(result);
            }
            catch (Exception error)
            {
                throw new MongoWorkersException(StringConsts.TODO_QUEUE_BSON_READ_ERROR.Args(queue, error.ToMessageWithType()), error);
            }
        }
示例#5
0
        public override void Complete(TodoQueue queue, TodoFrame todo, Exception error = null, object transaction = null)
        {
            if (Disposed || queue == null || !todo.Assigned)
            {
                return;
            }

            //this provider ignores exceptions passed in error var
            m_Database[queue.Name].DeleteOne(Query.ID_EQ_GDID(todo.ID));
        }
示例#6
0
        public override void Put(TodoQueue queue, TodoFrame todo, object transaction)
        {
            if (Disposed || queue == null || !todo.Assigned)
            {
                return;
            }
            var tName = queue.Name;
            var doc   = toBSON(queue, todo);

            m_Database[tName].Insert(doc);
        }
示例#7
0
        public override void Update(TodoQueue queue, Todo todo, bool sysOnly, object transaction)
        {
            if (Disposed || queue == null || todo == null)
            {
                return;
            }

            var frame = new TodoFrame(todo, sysOnly ? (int?)null : TodoFrame.SERIALIZER_BSON);
            var doc   = toBSONUpdate(queue, frame, sysOnly);

            m_Database[queue.Name].Update(new UpdateEntry(Query.ID_EQ_GDID(todo.SysID), doc, false, false));
        }
示例#8
0
        public override IEnumerable <TodoFrame> Fetch(TodoQueue queue, DateTime utcNow)
        {
            if (Disposed || queue == null)
            {
                return(Enumerable.Empty <TodoFrame>());
            }

            var collection = m_Database[queue.Name];

#warning This needs revision
            //todo Napisat query - kak sdelat server-side SORT? mopjet sdelat ID ne GDID a vremya?
            //{ $query: {}, $orderby: { dt: 1 } }
            // akto sdelaet v mongo index? mojet ne xranit null v __sd a xranit MIN date vmesto null?

            //Mojet zdes nado sdelat Db.RunCommand i peredat sort tuda? Nujen index!
            //https://docs.mongodb.com/manual/reference/command/find/#dbcmd.find
            //kak eto vliyaet na mongo sort size buffer (32 mb? tam ili chtoto typa togo)?
            var query = new Query(
                @"{
         '$query': { sd: {'$lt': '$$now'} },
         '$orderby': { sd: 1}
        }",
                true, new TemplateArg(new BSONDateTimeElement("now", utcNow)));

            var total = queue.BatchSize;

            var result = new List <TodoFrame>();

            var fby = FetchBy;
            if (fby > total)
            {
                fby = total;
            }

            using (var cursor = collection.Find(query, fetchBy: fby))
                foreach (var doc in cursor)
                {
                    var todo = toFrame(queue, doc);
                    result.Add(todo);
                    var left = total - result.Count;
                    if (left == 0)
                    {
                        break;
                    }
                    if (cursor.FetchBy > left)
                    {
                        cursor.FetchBy = left;
                    }
                }

            return(result);
        }
示例#9
0
                                              private void processOneQueueBatch(TodoQueue queue, IEnumerable <TodoFrame> batch, DateTime utcNow)
                                              {
                                                  if (queue.Mode == TodoQueue.ExecuteMode.Sequential)
                                                  {
                                                      batch.OrderBy(t => t.StartDate).ForEach(todo => executeOne(queue, todo, utcNow));
                                                  }
                                                  else if (queue.Mode == TodoQueue.ExecuteMode.Parallel)
                                                  {
                                                      Parallel.ForEach(batch.OrderBy(t => t.StartDate), todo => executeOne(queue, todo, utcNow));
                                                  }
                                                  else//ParallelByKey
                                                  {
                                                      var tasks = new List <Task>();

                                                      var parallelTodos = batch.Where(t => t.ParallelKey == null).ToArray();
                                                      if (parallelTodos.Length > 0)
                                                      {
                                                          tasks.Add(Task.Factory.StartNew(ts => Parallel.ForEach(((IEnumerable <TodoFrame>)ts).OrderBy(t => t.StartDate), todo => executeOne(queue, todo, utcNow)), parallelTodos));
                                                      }

                                                      List <TodoFrame> todos       = null;
                                                      string           parallelKey = null;
                                                      foreach (var todo in batch.Where(t => t.ParallelKey != null).OrderBy(t => t.ParallelKey))
                                                      {
                                                          if (parallelKey != todo.ParallelKey)
                                                          {
                                                              if (todos != null)
                                                              {
                                                                  tasks.Add(Task.Factory.StartNew(ts => ((IEnumerable <TodoFrame>)ts).OrderBy(t => t.StartDate).ForEach(t => executeOne(queue, t, utcNow)), todos));
                                                              }
                                                              todos       = new List <TodoFrame>();
                                                              parallelKey = todo.ParallelKey;
                                                          }
                                                          todos.Add(todo);
                                                      }

                                                      if (todos != null)
                                                      {
                                                          tasks.Add(Task.Factory.StartNew(ts => ((IEnumerable <TodoFrame>)ts).OrderBy(t => t.StartDate).ForEach(t => executeOne(queue, t, utcNow)), todos));
                                                      }

                                                      Task.WaitAll(tasks.ToArray());
                                                  }
                                              }
示例#10
0
                                              private void processOneQueueCore(TodoQueue queue, DateTime utcNow)
                                              {
                                                  var fetched = m_QueueStore.Fetch(queue, utcNow);

                                                  try
                                                  {
                                                      var batch = fetched.Where(todo =>
                {
                    if (todo.CorrelationKey == null)
                    {
                        return(true);
                    }
                    return(tryLockCorrelatedProcessing(todo.CorrelationKey, todo.StartDate));
                }).ToList();//must materialize not to double lock

                                                      if (InstrumentationEnabled)
                                                      {
                                                          var fetchCount = fetched.Count();
                                                          m_stat_FetchedTodoCount.AddLong(ALL, fetchCount);
                                                          m_stat_FetchedTodoCount.AddLong(queue.Name, fetchCount);
                                                      }

                                                      processOneQueueBatch(queue, batch, utcNow);


                                                      if (InstrumentationEnabled)
                                                      {
                                                          m_stat_ProcessedTodoCount.AddLong(ALL, batch.Count);
                                                          m_stat_ProcessedTodoCount.AddLong(queue.Name, batch.Count);
                                                      }
                                                  }
                                                  finally
                                                  {
                                                      fetched.ForEach(todo =>
                {
                    if (todo.CorrelationKey == null)
                    {
                        return;
                    }
                    releaseCorrelatedProcessing(todo.CorrelationKey);
                });
                                                  }
                                              }
示例#11
0
                                              private void complete(TodoQueue queue, TodoFrame todo, Exception error, object transaction = null)
                                              {
                                                  try
                                                  {
                                                      m_QueueStore.Complete(queue, todo, error, transaction);

                                                      if (error != null)
                                                      {
                                                          WriteLog(MessageType.Error, "complete('{0}')".Args(queue.Name), "Completed with error: " + error.ToMessageWithType(), error);
                                                      }

                                                      if (InstrumentationEnabled)
                                                      {
                                                          m_stat_CompletedTodoCount.IncrementLong(ALL);
                                                          m_stat_CompletedTodoCount.IncrementLong(queue.Name);

                                                          if (error != null)
                                                          {
                                                              m_stat_CompletedErrorTodoCount.IncrementLong(ALL);
                                                              m_stat_CompletedErrorTodoCount.IncrementLong(queue.Name);
                                                          }
                                                          else
                                                          {
                                                              m_stat_CompletedOkTodoCount.IncrementLong(ALL);
                                                              m_stat_CompletedOkTodoCount.IncrementLong(queue.Name);
                                                          }
                                                      }
                                                  }
                                                  catch (Exception e)
                                                  {
                                                      var from = "complete('{0}')".Args(queue.Name);
                                                      WriteLog(MessageType.Critical, from, "{0} Leaked: {1}".Args(todo, e.ToMessageWithType()), e);
                                                      if (InstrumentationEnabled)
                                                      {
                                                          m_stat_QueueOperationErrorCount.IncrementLong(ALL);
                                                          m_stat_QueueOperationErrorCount.IncrementLong(from);
                                                      }
                                                  }
                                              }
示例#12
0
        private BSONDocument toBSON(TodoQueue queue, TodoFrame todo)
        {
            var result = new BSONDocument();
            var t      = todo.GetType();

            result.Set(DataDocConverter.GDID_CLRtoBSON(Query._ID, todo.ID));

            result.Set(new BSONStringElement(FLD_TODO_TYPE, todo.Type.ToString()));
            result.Set(new BSONDateTimeElement(FLD_TODO_CREATETIMESTAMP, todo.CreateTimestampUTC));

            result.Set(elmStr(FLD_TODO_SHARDINGKEY, todo.ShardingKey));
            result.Set(elmStr(FLD_TODO_PARALLELKEY, todo.ParallelKey));
            result.Set(new BSONInt32Element(FLD_TODO_PRIORITY, todo.Priority));
            result.Set(new BSONDateTimeElement(FLD_TODO_STARTDATE, todo.StartDate));
            result.Set(elmStr(FLD_TODO_CORRELATIONKEY, todo.CorrelationKey));
            result.Set(new BSONInt32Element(FLD_TODO_STATE, todo.State));
            result.Set(new BSONInt32Element(FLD_TODO_TRIES, todo.Tries));

            result.Set(new BSONInt32Element(FLD_TODO_SERIALIZER, todo.Serializer));
            result.Set(elmBin(FLD_TODO_CONTENT, todo.Content));

            return(result);
        }
                                              private void enqueue(TodoQueue queue, TodoFrame[] todos)
                                              {
                                                  var tx = m_QueueStore.BeginTransaction(queue);

                                                  try
                                                  {
                                                      enqueueCore(queue, todos, tx);
                                                      m_QueueStore.CommitTransaction(queue, tx);
                                                  }
                                                  catch (Exception error)
                                                  {
                                                      m_QueueStore.RollbackTransaction(queue, tx);

                                                      var from = "enqueue('{0}')".Args(queue.Name);
                                                      WriteLog(MessageType.CatastrophicError, from, error.ToMessageWithType(), error);
                                                      if (InstrumentationEnabled)
                                                      {
                                                          m_stat_QueueOperationErrorCount.IncrementLong(ALL);
                                                          m_stat_QueueOperationErrorCount.IncrementLong(from);
                                                      }

                                                      throw new WorkersException(StringConsts.TODO_ENQUEUE_TX_BODY_ERROR.Args(queue.Name, error.ToMessageWithType()), error);
                                                  }
                                              }
示例#14
0
        private BSONDocument toBSONUpdate(TodoQueue queue, TodoFrame todo, bool sysOnly)
        {
            var setDoc = new BSONDocument();

            setDoc.Set(elmStr(FLD_TODO_SHARDINGKEY, todo.ShardingKey));
            setDoc.Set(elmStr(FLD_TODO_PARALLELKEY, todo.ParallelKey));
            setDoc.Set(new BSONInt32Element(FLD_TODO_PRIORITY, todo.Priority));
            setDoc.Set(new BSONDateTimeElement(FLD_TODO_STARTDATE, todo.StartDate));
            setDoc.Set(elmStr(FLD_TODO_CORRELATIONKEY, todo.CorrelationKey));
            setDoc.Set(new BSONInt32Element(FLD_TODO_STATE, todo.State));
            setDoc.Set(new BSONInt32Element(FLD_TODO_TRIES, todo.Tries));

            if (!sysOnly)
            {
                setDoc.Set(new BSONInt32Element(FLD_TODO_SERIALIZER, todo.Serializer));
                setDoc.Set(elmBin(FLD_TODO_CONTENT, todo.Content));
            }

            var result = new BSONDocument();

            result.Set(new BSONDocumentElement("$set", setDoc));

            return(result);
        }
 private bool checkDupsInHostset(TodoQueue queue, TodoFrame todo)
 {
     return(false); // TODO implement
 }
示例#16
0
 public abstract object BeginTransaction(TodoQueue queue);
示例#17
0
 public abstract void CommitTransaction(TodoQueue queue, object transaction);
示例#18
0
 public abstract void RollbackTransaction(TodoQueue queue, object transaction);
示例#19
0
 public abstract void Put(TodoQueue queue, TodoFrame todo, object transaction);
示例#20
0
 public abstract void Update(TodoQueue queue, Todo todo, bool sysOnly, object transaction);
示例#21
0
 public abstract void Complete(TodoQueue queue, TodoFrame todo, Exception error = null, object transaction = null);
示例#22
0
 public override void RollbackTransaction(TodoQueue queue, object transaction)
 {
 }
示例#23
0
 public override int GetInboundCapacity(TodoQueue queue)
 {
     return(TodoQueueService.FULL_BATCH_SIZE);
 }
示例#24
0
 public override void CommitTransaction(TodoQueue queue, object transaction)
 {
 }
示例#25
0
 public override object BeginTransaction(TodoQueue queue)
 {
     return(null);
 }
示例#26
0
 public abstract TodoFrame FetchLatestCorrelated(TodoQueue queue, string correlationKey, DateTime utcStartingFrom);
                                              private void enqueueCore(TodoQueue queue, TodoFrame[] todos, object tx)
                                              {
                                                  foreach (var todo in todos)
                                                  {
                                                      if (!todo.Assigned)
                                                      {
                                                          continue;
                                                      }

                                                      //20171114 If the todo was already submitted, then do nothing
                                                      var isdup = checkDups(queue, todo);
                                                      if (isdup)
                                                      {
                                                          if (InstrumentationEnabled)
                                                          {
                                                              var from = "enqueue-dup('{0}')".Args(queue.Name);
                                                              m_stat_TodoDuplicationCount.IncrementLong(ALL);
                                                              m_stat_TodoDuplicationCount.IncrementLong(from);
                                                          }
                                                          continue;
                                                      }


                                                      if (todo.CorrelationKey == null)//regular todos just add
                                                      {
                                                          put(queue, todo, tx, true);
                                                          continue;
                                                      }

                                                      //Correlated -------------------------------------------------------------
                                                      var utcNow         = App.TimeSource.UTCNow;//warning locking depends on this accurate date
                                                      var utcCorrelateSD = lockCorrelatedEnqueue(todo.CorrelationKey, utcNow);
                                                      try
                                                      {
                                                          var existing = m_QueueStore.FetchLatestCorrelated(queue, todo.CorrelationKey, utcCorrelateSD);
                                                          if (!existing.Assigned) //no existing with same correlation, just add
                                                          {
                                                              put(queue, todo, tx, true);
                                                              continue;
                                                          }

                                                          var todoExisting = existing.Materialize(App.ProcessManager.TodoTypeResolver) as CorrelatedTodo;
                                                          var todoAnother  = todo.Materialize(App.ProcessManager.TodoTypeResolver) as CorrelatedTodo;
                                                          if (todoExisting == null || todoAnother == null)//safeguard
                                                          {
                                                              put(queue, todo, tx, true);
                                                              continue;
                                                          }

                                                          CorrelatedTodo.MergeResult mergeResult;
                                                          try
                                                          {
                                                              mergeResult = todoExisting.Merge(this, utcNow, todoAnother);
                                                          }
                                                          catch (Exception error)
                                                          {
                                                              throw new WorkersException(StringConsts.TODO_CORRELATED_MERGE_ERROR.Args(todoExisting, todoAnother, error.ToMessageWithType()), error);
                                                          }

                                                          if (InstrumentationEnabled)
                                                          {
                                                              m_stat_MergedTodoCount.IncrementLong(ALL);
                                                              m_stat_MergedTodoCount.IncrementLong(queue.Name);
                                                              m_stat_MergedTodoCount.IncrementLong(queue.Name + ":" + mergeResult);
                                                          }

                                                          if (mergeResult == CorrelatedTodo.MergeResult.Merged)
                                                          {
                                                              update(queue, todoExisting, sysOnly: false, leak: true, transaction: tx);
                                                              continue;
                                                          }
                                                          else if (mergeResult == CorrelatedTodo.MergeResult.IgnoreAnother)
                                                          {
                                                              continue;//do nothing, just drop another as-if never existed
                                                          }

                                                          //Else, merge == CorrelatedTodo.MergeResult.None
                                                          put(queue, todo, tx, true);
                                                      }
                                                      finally
                                                      {
                                                          releaseCorrelatedEnqueue(todo.CorrelationKey);
                                                      }
                                                  }//foreach
                                              }
示例#28
0
                                              private void executeOne(TodoQueue queue, TodoFrame todoFrame, DateTime utcNow)//must not leak
                                              {
                                                  try
                                                  {
                                                      if (!Running)
                                                      {
                                                          return;
                                                      }

                                                      Todo todo;
                                                      try
                                                      {
                                                          todo = todoFrame.Materialize(App.ProcessManager.TodoTypeResolver);
                                                          App.DependencyInjector.InjectInto(todo);
                                                      }
                                                      catch (Exception me)
                                                      {
                                                          var from = "executeOne('{0}').Materialize".Args(queue.Name);
                                                          WriteLog(MessageType.Critical, from, "Frame materialization: " + me.ToMessageWithType(), me);
                                                          if (InstrumentationEnabled)
                                                          {
                                                              m_stat_QueueOperationErrorCount.IncrementLong(ALL);
                                                              m_stat_QueueOperationErrorCount.IncrementLong(from);
                                                          }
                                                          throw;
                                                      }

                                                      var wasState = todo.SysState;
                                                      while (todo.SysState != Todo.ExecuteState.Complete)
                                                      {
                                                          var nextState = todo.Execute(this, utcNow);

                                                          if (nextState == Todo.ExecuteState.ReexecuteUpdatedAfterError)
                                                          {
                                                              todo.SysTries++;
                                                              var ms = todo.RetryAfterErrorInMs(utcNow);
                                                              if (ms > 0)
                                                              {
                                                                  todo.SysStartDate = todo.SysStartDate.AddMilliseconds(ms);
                                                              }
                                                              update(queue, todo, false);
                                                              return;
                                                          }

                                                          if (nextState == Todo.ExecuteState.ReexecuteAfterError)
                                                          {
                                                              todo.SysTries++;
                                                              var ms = todo.RetryAfterErrorInMs(utcNow);
                                                              if (ms > 0)
                                                              {
                                                                  todo.SysStartDate = todo.SysStartDate.AddMilliseconds(ms);
                                                              }
                                                              if (ms >= 0 || todo.SysState != wasState)
                                                              {
                                                                  update(queue, todo, true);
                                                              }
                                                              return;
                                                          }

                                                          if (nextState == Todo.ExecuteState.ReexecuteUpdated)
                                                          {
                                                              update(queue, todo, false);
                                                              return;
                                                          }

                                                          if (nextState == Todo.ExecuteState.ReexecuteSysUpdated)
                                                          {
                                                              update(queue, todo, true);
                                                              return;
                                                          }

                                                          if (nextState == Todo.ExecuteState.Reexecute)
                                                          {
                                                              if (todo.SysState != wasState)
                                                              {
                                                                  update(queue, todo, true);
                                                              }
                                                              return;
                                                          }

                                                          todo.SysTries = 0;
                                                          todo.SysState = nextState;
                                                      }

                                                      complete(queue, todoFrame, null);
                                                  }
                                                  catch (Exception error)
                                                  {
                                                      complete(queue, todoFrame, error);
                                                  }
                                              }
示例#29
0
 public abstract IEnumerable <TodoFrame> Fetch(TodoQueue queue, DateTime utcNow);
示例#30
0
 public abstract int GetInboundCapacity(TodoQueue queue);