private void QueryLatestOffset(ConsumerLeaseKey key, long correlationId)
        {

            while (!IsClosed() && !leaseRef.ReadFullFence().Expired)
            {

                Endpoint endpoint = EndpointManager.GetEndpoint(Context.Topic.Name, PartitionId);
                if (endpoint == null)
                {
                    log.Warn(string.Format("No endpoint found for topic {0} partition {1}, will retry later", Context.Topic.Name, PartitionId));
                    noEndpointSchedulePolicy.Fail(true);
                    continue;
                }
                else
                {
                    noEndpointSchedulePolicy.Succeess();
                }

                SettableFuture<QueryOffsetResultCommand> future = SettableFuture<QueryOffsetResultCommand>.Create();

                QueryOffsetCommand cmd = new QueryOffsetCommand(Context.Topic.Name, PartitionId, Context.GroupId);

                cmd.Header.CorrelationId = correlationId;
                cmd.Future = future;

                QueryOffsetResultCommand offsetRes = null;

                int timeout = Config.QueryOffsetTimeoutMillis;

                queryOffsetResultMonitor.Monitor(cmd);
                EndpointClient.WriteCommand(endpoint, cmd, timeout);

                try
                {
                    offsetRes = future.Get(timeout);
                }
                catch (Exception e)
                {
                }
                finally
                {
                    queryOffsetResultMonitor.Remove(cmd);
                }

                if (offsetRes != null && offsetRes.Offset != null)
                {
                    offset.WriteFullFence(offsetRes.Offset);
                    return;
                }
                else
                {
                    noEndpointSchedulePolicy.Fail(true);
                }

            }
        }
        protected override void DoBeforeConsuming(ConsumerLeaseKey key, long correlationId)
        {
            noEndpointSchedulePolicy = new ExponentialSchedulePolicy(Config.NoEndpointWaitBaseMillis,
                Config.NoEndpointWaitMaxMillis);

            QueryLatestOffset(key, correlationId);
            // reset policy
            noEndpointSchedulePolicy.Succeess();

            pullMessagesTask.WriteFullFence(new PullMessagesTask(correlationId, noEndpointSchedulePolicy, this));
        }
 protected override void DoAfterConsuming(ConsumerLeaseKey key, long correlationId)
 {
     pullMessagesTask.WriteFullFence(null);
 }
 protected override void DoBeforeConsuming(ConsumerLeaseKey key, long correlationId)
 {
     ISchedulePolicy noEndpointSchedulePolicy = new ExponentialSchedulePolicy(Config.NoEndpointWaitBaseMillis, Config.NoEndpointWaitMaxMillis);
     pullMessagesTask.WriteFullFence(new DefaultPullMessagesTask(correlationId, noEndpointSchedulePolicy, this));
 }
 public RenewLeaseTask(ConsumerLeaseKey key, long delay)
 {
     Key = key;
     Delay = delay;
 }
 protected abstract void DoAfterConsuming(ConsumerLeaseKey key, long correlationId);
        private void AcquireLease(ConsumerLeaseKey key)
        {
            long nextTryTime = SystemClockService.Now();

            while (!IsClosed())
            {
                try
                {
                    WaitForNextTryTime(nextTryTime);

                    if (IsClosed())
                    {
                        return;
                    }

                    LeaseAcquireResponse response = LeaseManager.TryAcquireLease(key);

                    if (response != null && response.Acquired && !response.Lease.Expired)
                    {
                        leaseRef.WriteFullFence(response.Lease);
                        ScheduleRenewLeaseTask(key,
                            leaseRef.ReadFullFence().RemainingTime - Config.RenewLeaseTimeMillisBeforeExpired);
                        return;
                    }
                    else
                    {
                        if (response != null && response.NextTryTime > 0)
                        {
                            nextTryTime = response.NextTryTime;
                        }
                        else
                        {
                            nextTryTime = SystemClockService.Now() + Config.DefaultLeaseAcquireDelayMillis;
                        }
                    }
                }
                catch (Exception e)
                {
                    log.Error(string.Format("Exception occurred while acquiring lease(topic={0}, partition={1}, groupId={2}, sessionId={3})",
                            Context.Topic.Name, PartitionId, Context.GroupId, Context.SessionId), e);
                }
            }
        }
 protected void ScheduleRenewLeaseTask(ConsumerLeaseKey key, long delay)
 {
     int sKey = scheduleKey.AtomicAddAndGet(1);
     renewLeaseTaskExecutor.Produce(sKey, new RenewLeaseTask(key, delay), (int)delay);
 }
        private void StartConsuming(ConsumerLeaseKey key, long correlationId)
        {
            ConsumerNotifier.Register(correlationId, Context);
            DoBeforeConsuming(key, correlationId);
            msgs.Clear();
            ISchedulePolicy noMessageSchedulePolicy = new ExponentialSchedulePolicy(Config.NoMessageWaitBaseMillis, Config.NoMessageWaitMaxMillis);

            while (!IsClosed() && !leaseRef.ReadFullFence().Expired)
            {

                try
                {
                    // if leaseRemainingTime < stopConsumerTimeMillsBeforLeaseExpired, stop
                    if (leaseRef.ReadFullFence().RemainingTime <= Config.StopConsumerTimeMillsBeforLeaseExpired)
                    {
                        break;
                    }

                    if (msgs.Count == 0)
                    {
                        SchedulePullMessagesTask();
                    }

                    if (msgs.Count != 0)
                    {
                        ConsumeMessages(correlationId);
                        noMessageSchedulePolicy.Succeess();
                    }
                    else
                    {
                        noMessageSchedulePolicy.Fail(true);
                    }

                }
                catch (Exception e)
                {
                    log.Error(string.Format("Exception occurred while consuming message(topic={0}, partition={1}, groupId={2}, sessionId={3})",
                            Context.Topic.Name, PartitionId, Context.GroupId, Context.SessionId), e);
                }
            }

            ConsumerNotifier.Deregister(correlationId);
            leaseRef.WriteFullFence(null);
            DoAfterConsuming(key, correlationId);
        }
        public void Start()
        {
            log.Info(string.Format("Consumer started(mode={0}, topic={1}, partition={2}, groupId={3}, sessionId={4})",
                    Context.ConsumerType, Context.Topic.Name, PartitionId, Context.GroupId, Context.SessionId));
            ConsumerLeaseKey key = new ConsumerLeaseKey(new Tpg(Context.Topic.Name, PartitionId,
                                           Context.GroupId), Context.SessionId);
            while (!IsClosed())
            {
                try
                {
                    
                    AcquireLease(key);

                    if (!IsClosed() && leaseRef.ReadFullFence() != null && !leaseRef.ReadFullFence().Expired)
                    {
                        long correlationId = CorrelationIdGenerator.generateCorrelationId();
                        log.Info(string.Format(
                                "Consumer continue consuming(mode={0}, topic={1}, partition={2}, groupId={3}, correlationId={4}, sessionId={5}), since lease acquired",
                                Context.ConsumerType, Context.Topic.Name, PartitionId, Context.GroupId, correlationId, Context.SessionId));


                        StartConsuming(key, correlationId);

                        log.Info(string.Format(
                                "Consumer pause consuming(mode={0}, topic={1}, partition={2}, groupId={3}, correlationId={4}, sessionId={5}), since lease expired",
                                Context.ConsumerType, Context.Topic.Name, PartitionId, Context.GroupId, correlationId, Context.SessionId));
                    }
                }
                catch (Exception e)
                {
                    log.Error(string.Format("Exception occurred in consumer's run method(topic={0}, partition={1}, groupId={2}, sessionId={3})",
                            Context.Topic.Name, PartitionId, Context.GroupId, Context.SessionId), e);
                }
            }

            pullMessageTaskExecutor.Shutdown();
            renewLeaseTaskExecutor.Shutdown();
            log.Info(string.Format("Consumer stopped(mode={0}, topic={1}, partition={2}, groupId={3}, sessionId={4})", 
                    Context.ConsumerType, Context.Topic.Name, PartitionId, Context.GroupId, Context.SessionId));
        }