Пример #1
0
        private TodoFrame toFrame(TodoQueue queue, BSONDocument doc)
        {
            try
            {
                var result = new TodoFrame();

                result.ID   = RowConverter.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);
            }
        }
Пример #2
0
        public override TodoFrame FetchLatestCorrelated(TodoQueue queue, string correlationKey, DateTime utcStartingFrom)
        {
            if (DisposeStarted || 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);
        }
Пример #3
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);
         Log(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;
         }
     }
 }
Пример #4
0
                                          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);
                                          }
Пример #5
0
        public override void Complete(TodoQueue queue, TodoFrame todo, Exception error = null, object transaction = null)
        {
            if (DisposeStarted || 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 (DisposeStarted || 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 (DisposeStarted || 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 (DisposeStarted || queue == null)
            {
                return(Enumerable.Empty <TodoFrame>());
            }

            var collection = m_Database[queue.Name];

            //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)
                                                  {
                                                      Log(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);
                                                  Log(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(RowConverter.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);
        }
Пример #13
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);
        }
Пример #14
0
                                          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);
                                                  Log(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);
                                              }
                                          }
Пример #15
0
                                          private void executeOne(TodoQueue queue, TodoFrame todoFrame, DateTime utcNow)//must not leak
                                          {
                                              try
                                              {
                                                  if (!Running)
                                                  {
                                                      return;
                                                  }

                                                  Todo todo;
                                                  try
                                                  {
                                                      todo = todoFrame.Materialize(AgniSystem.ProcessManager.TodoTypeResolver);
                                                  }
                                                  catch (Exception me)
                                                  {
                                                      var from = "executeOne('{0}').Materialize".Args(queue.Name);
                                                      Log(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);
                                              }
                                          }
Пример #16
0
 public abstract void CommitTransaction(TodoQueue queue, object transaction);
Пример #17
0
 public override int GetInboundCapacity(TodoQueue queue)
 {
     return(TodoQueueService.FULL_BATCH_SIZE);
 }
Пример #18
0
 public override void RollbackTransaction(TodoQueue queue, object transaction)
 {
 }
Пример #19
0
 public override void CommitTransaction(TodoQueue queue, object transaction)
 {
 }
Пример #20
0
 public override object BeginTransaction(TodoQueue queue)
 {
     return(null);
 }
Пример #21
0
 private bool checkDupsInHostset(TodoQueue queue, TodoFrame todo)
 {
     return(false); // TODO implement
 }
Пример #22
0
                                          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(AgniSystem.ProcessManager.TodoTypeResolver) as CorrelatedTodo;
                                                      var todoAnother  = todo.Materialize(AgniSystem.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
                                          }
Пример #23
0
 public abstract void Put(TodoQueue queue, TodoFrame todo, object transaction);
Пример #24
0
 public abstract TodoFrame FetchLatestCorrelated(TodoQueue queue, string correlationKey, DateTime utcStartingFrom);
Пример #25
0
 public abstract void Update(TodoQueue queue, Todo todo, bool sysOnly, object transaction);
Пример #26
0
 public abstract void Complete(TodoQueue queue, TodoFrame todo, Exception error = null, object transaction = null);
Пример #27
0
 public abstract object BeginTransaction(TodoQueue queue);
Пример #28
0
 public abstract void RollbackTransaction(TodoQueue queue, object transaction);
Пример #29
0
 public abstract IEnumerable <TodoFrame> Fetch(TodoQueue queue, DateTime utcNow);
Пример #30
0
 public abstract int GetInboundCapacity(TodoQueue queue);