internal PersistentStreamPullingAgent(
            SystemTargetGrainId id,
            string strProviderName,
            ILoggerFactory loggerFactory,
            IStreamPubSub streamPubSub,
            IStreamFilter streamFilter,
            QueueId queueId,
            StreamPullingAgentOptions options,
            SiloAddress siloAddress)
            : base(id, siloAddress, true, loggerFactory)
        {
            if (strProviderName == null)
            {
                throw new ArgumentNullException("runtime", "PersistentStreamPullingAgent: strProviderName should not be null");
            }

            QueueId            = queueId;
            streamProviderName = strProviderName;
            pubSub             = streamPubSub;
            this.streamFilter  = streamFilter;
            pubSubCache        = new Dictionary <InternalStreamId, StreamConsumerCollection>();
            this.options       = options;
            numMessages        = 0;

            logger = loggerFactory.CreateLogger($"{this.GetType().Namespace}.{streamProviderName}");
            logger.Info(ErrorCode.PersistentStreamPullingAgent_01,
                        "Created {0} {1} for Stream Provider {2} on silo {3} for Queue {4}.",
                        GetType().Name, ((ISystemTargetBase)this).GrainId.ToString(), streamProviderName, Silo, QueueId.ToStringWithHashCode());
            numReadMessagesCounter = CounterStatistic.FindOrCreate(new StatisticName(StatisticNames.STREAMS_PERSISTENT_STREAM_NUM_READ_MESSAGES, StatisticUniquePostfix));
            numSentMessagesCounter = CounterStatistic.FindOrCreate(new StatisticName(StatisticNames.STREAMS_PERSISTENT_STREAM_NUM_SENT_MESSAGES, StatisticUniquePostfix));
            // TODO: move queue cache size statistics tracking into queue cache implementation once Telemetry APIs and LogStatistics have been reconciled.
            //IntValueStatistic.FindOrCreate(new StatisticName(StatisticNames.STREAMS_PERSISTENT_STREAM_QUEUE_CACHE_SIZE, statUniquePostfix), () => queueCache != null ? queueCache.Size : 0);
        }
Esempio n. 2
0
        public async Task <IPersistentStreamPullingManager> InitializePullingAgents(
            string streamProviderName,
            IQueueAdapterFactory adapterFactory,
            IQueueAdapter queueAdapter)
        {
            IStreamQueueBalancer queueBalancer = CreateQueueBalancer(streamProviderName);
            var managerId           = SystemTargetGrainId.Create(Constants.StreamPullingAgentManagerType, this.siloDetails.SiloAddress, streamProviderName);
            var pubsubOptions       = this.ServiceProvider.GetOptionsByName <StreamPubSubOptions>(streamProviderName);
            var pullingAgentOptions = this.ServiceProvider.GetOptionsByName <StreamPullingAgentOptions>(streamProviderName);
            var filter  = this.ServiceProvider.GetServiceByName <IStreamFilter>(streamProviderName) ?? new NoOpStreamFilter();
            var manager = new PersistentStreamPullingManager(
                managerId,
                streamProviderName,
                this.PubSub(pubsubOptions.PubSubType),
                adapterFactory,
                queueBalancer,
                filter,
                pullingAgentOptions,
                this.loggerFactory,
                this.siloDetails.SiloAddress,
                queueAdapter);

            var catalog = this.ServiceProvider.GetRequiredService <Catalog>();

            catalog.RegisterSystemTarget(manager);

            // Init the manager only after it was registered locally.
            var pullingAgentManager = manager.AsReference <IPersistentStreamPullingManager>();

            // Need to call it as a grain reference though.
            await pullingAgentManager.Initialize();

            return(pullingAgentManager);
        }
Esempio n. 3
0
        public TGrainInterface GetSystemTarget <TGrainInterface>(GrainType grainType, SiloAddress destination)
            where TGrainInterface : ISystemTarget
        {
            var grainId = SystemTargetGrainId.Create(grainType, destination);

            return(this.GetSystemTarget <TGrainInterface>(grainId.GrainId));
        }
Esempio n. 4
0
        /// <summary>
        /// Take responsibility for a set of new queues that were assigned to me via a new range.
        /// We first create one pulling agent for every new queue and store them in our internal data structure, then try to initialize the agents.
        /// ERROR HANDLING:
        ///     The responsibility to handle initialization and shutdown failures is inside the Agents code.
        ///     The manager will call Initialize once and log an error. It will not call initialize again and will assume initialization has succeeded.
        ///     Same applies to shutdown.
        /// </summary>
        /// <param name="myQueues"></param>
        /// <param name="failOnInit"></param>
        /// <returns></returns>
        private async Task AddNewQueues(IEnumerable <QueueId> myQueues, bool failOnInit)
        {
            // Create agents for queues in range that we don't yet have.
            // First create them and store in local queuesToAgentsMap.
            // Only after that Initialize them all.
            var agents = new List <PersistentStreamPullingAgent>();

            foreach (var queueId in myQueues)
            {
                if (queuesToAgentsMap.ContainsKey(queueId))
                {
                    continue;
                }
                try
                {
                    var agentIdNumber = Interlocked.Increment(ref nextAgentId);
                    var agentId       = SystemTargetGrainId.Create(Constants.StreamPullingAgentType, this.Silo, $"{streamProviderName}_{agentIdNumber}_{queueId.ToStringWithHashCode()}");
                    IStreamFailureHandler deliveryFailureHandler = await adapterFactory.GetDeliveryFailureHandler(queueId);

                    var agent = new PersistentStreamPullingAgent(agentId, streamProviderName, this.loggerFactory, pubSub, streamFilter, queueId, this.options, this.Silo, queueAdapter, queueAdapterCache, deliveryFailureHandler);
                    this.ActivationServices.GetRequiredService <Catalog>().RegisterSystemTarget(agent);
                    queuesToAgentsMap.Add(queueId, agent);
                    agents.Add(agent);
                }
                catch (Exception exc)
                {
                    logger.Error(ErrorCode.PersistentStreamPullingManager_07, "Exception while creating PersistentStreamPullingAgent.", exc);
                    // What should we do? This error is not recoverable and considered a bug. But we don't want to bring the silo down.
                    // If this is when silo is starting and agent is initializing, fail the silo startup. Otherwise, just swallow to limit impact on other receivers.
                    if (failOnInit)
                    {
                        throw;
                    }
                }
            }

            try
            {
                var initTasks = new List <Task>();
                foreach (var agent in agents)
                {
                    initTasks.Add(InitAgent(agent));
                }
                await Task.WhenAll(initTasks);
            }
            catch
            {
                // Just ignore this exception and proceed as if Initialize has succeeded.
                // We already logged individual exceptions for individual calls to Initialize. No need to log again.
            }
            if (agents.Count > 0)
            {
                Log(ErrorCode.PersistentStreamPullingManager_08, "Added {0} new queues: {1}. Now own total of {2} queues: {3}",
                    agents.Count,
                    Utils.EnumerableToString(agents, agent => agent.QueueId.ToString()),
                    NumberRunningAgents,
                    PrintQueues(queuesToAgentsMap.Keys));
            }
        }
Esempio n. 5
0
        protected override void OnReceivedMessage(Message msg)
        {
            // Don't process messages that have already timed out
            if (msg.IsExpired)
            {
                this.MessagingTrace.OnDropExpiredMessage(msg, MessagingStatisticsGroup.Phase.Receive);
                return;
            }

            // Are we overloaded?
            if (this.overloadDetector.Overloaded)
            {
                MessagingStatisticsGroup.OnRejectedMessage(msg);
                Message rejection = this.MessageFactory.CreateRejectionResponse(msg, Message.RejectionTypes.GatewayTooBusy, "Shedding load");
                this.messageCenter.TryDeliverToProxy(rejection);
                if (this.Log.IsEnabled(LogLevel.Debug))
                {
                    this.Log.LogDebug("Rejecting a request due to overloading: {Message}", msg.ToString());
                }
                loadSheddingCounter.Increment();
                return;
            }

            SiloAddress targetAddress = this.gateway.TryToReroute(msg);

            msg.SendingSilo = this.myAddress;
            if (targetAddress is null)
            {
                // reroute via Dispatcher
                msg.TargetSilo       = null;
                msg.TargetActivation = default;
                msg.ClearTargetAddress();

                if (SystemTargetGrainId.TryParse(msg.TargetGrain, out var systemTargetId))
                {
                    msg.TargetSilo       = this.myAddress;
                    msg.TargetGrain      = systemTargetId.WithSiloAddress(this.myAddress).GrainId;
                    msg.TargetActivation = ActivationId.GetDeterministic(msg.TargetGrain);
                }

                MessagingStatisticsGroup.OnMessageReRoute(msg);
                this.messageCenter.RerouteMessage(msg);
            }
            else
            {
                // send directly
                msg.TargetSilo = targetAddress;

                if (SystemTargetGrainId.TryParse(msg.TargetGrain, out var systemTargetId))
                {
                    msg.TargetGrain      = systemTargetId.WithSiloAddress(targetAddress).GrainId;
                    msg.TargetActivation = ActivationId.GetDeterministic(msg.TargetGrain);
                }

                this.messageCenter.SendMessage(msg);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Get a reference to the <see cref="GrainService"/> responsible for actioning the request based on the <paramref name="callingGrainId"/>.
        /// </summary>
        protected TGrainService GetGrainService(GrainId callingGrainId)
        {
            var hashCode    = callingGrainId.GetUniformHashCode();
            var destination = ringProvider.GetPrimaryTargetSilo(hashCode);

            var grainId      = SystemTargetGrainId.CreateGrainServiceGrainId(grainType, destination);
            var grainService = grainFactory.GetSystemTarget <TGrainService>(grainId);

            return(grainService);
        }
Esempio n. 7
0
        /// <summary>
        /// Currently we only support a single GrainService per Silo, when multiple are supported we will request the number of GrainServices to partition per silo here.
        /// </summary>
        protected GrainServiceClient(IServiceProvider serviceProvider)
        {
            grainFactory = serviceProvider.GetRequiredService <IInternalGrainFactory>();
            ringProvider = serviceProvider.GetRequiredService <IConsistentRingProvider>();

            // GrainInterfaceMap only holds IGrain types, not ISystemTarget types, so resolved via Orleans.CodeGeneration.
            // Resolve this before merge.
            var grainTypeCode = GrainInterfaceUtils.GetGrainClassTypeCode(typeof(TGrainService));

            grainType = SystemTargetGrainId.CreateGrainServiceGrainType(grainTypeCode, null);
        }
Esempio n. 8
0
        private static IGrainService GrainServiceFactory(Type serviceType, IServiceProvider services)
        {
            var grainServiceInterfaceType = serviceType.GetInterfaces().FirstOrDefault(x => x.GetInterfaces().Contains(typeof(IGrainService)));

            if (grainServiceInterfaceType is null)
            {
                throw new InvalidOperationException(String.Format($"Cannot find an interface on {serviceType.FullName} which implements IGrainService"));
            }

            var typeCode     = GrainInterfaceUtils.GetGrainClassTypeCode(grainServiceInterfaceType);
            var grainId      = SystemTargetGrainId.CreateGrainServiceGrainId(typeCode, null, SiloAddress.Zero);
            var grainService = (IGrainService)ActivatorUtilities.CreateInstance(services, serviceType, grainId);

            return(grainService);
        }
        internal PersistentStreamPullingManager(
            SystemTargetGrainId managerId,
            string strProviderName,
            IStreamProviderRuntime runtime,
            IStreamPubSub streamPubSub,
            IQueueAdapterFactory adapterFactory,
            IStreamQueueBalancer streamQueueBalancer,
            IStreamFilter streamFilter,
            StreamPullingAgentOptions options,
            ILoggerFactory loggerFactory,
            SiloAddress siloAddress)
            : base(managerId, siloAddress, lowPriority: false, loggerFactory)
        {
            if (string.IsNullOrWhiteSpace(strProviderName))
            {
                throw new ArgumentNullException("strProviderName");
            }
            if (runtime == null)
            {
                throw new ArgumentNullException("runtime", "IStreamProviderRuntime runtime reference should not be null");
            }
            if (streamPubSub == null)
            {
                throw new ArgumentNullException("streamPubSub", "StreamPubSub reference should not be null");
            }
            if (streamQueueBalancer == null)
            {
                throw new ArgumentNullException("streamQueueBalancer", "IStreamQueueBalancer streamQueueBalancer reference should not be null");
            }

            queuesToAgentsMap      = new Dictionary <QueueId, PersistentStreamPullingAgent>();
            streamProviderName     = strProviderName;
            providerRuntime        = runtime;
            pubSub                 = streamPubSub;
            this.options           = options;
            nonReentrancyGuarantor = new AsyncSerialExecutor();
            latestRingNotificationSequenceNumber = 0;
            latestCommandNumber = 0;
            queueBalancer       = streamQueueBalancer;
            this.streamFilter   = streamFilter;
            this.adapterFactory = adapterFactory;

            queueAdapterCache = adapterFactory.GetQueueAdapterCache();
            logger            = loggerFactory.CreateLogger($"{GetType().FullName}.{streamProviderName}");
            Log(ErrorCode.PersistentStreamPullingManager_01, "Created {0} for Stream Provider {1}.", GetType().Name, streamProviderName);
            this.loggerFactory = loggerFactory;
            IntValueStatistic.FindOrCreate(new StatisticName(StatisticNames.STREAMS_PERSISTENT_STREAM_NUM_PULLING_AGENTS, strProviderName), () => queuesToAgentsMap.Count);
        }
        internal PersistentStreamPullingAgent(
            SystemTargetGrainId id,
            string strProviderName,
            ILoggerFactory loggerFactory,
            IStreamPubSub streamPubSub,
            IStreamFilter streamFilter,
            QueueId queueId,
            StreamPullingAgentOptions options,
            SiloAddress siloAddress,
            IQueueAdapter queueAdapter,
            IQueueAdapterCache queueAdapterCache,
            IStreamFailureHandler streamFailureHandler)
            : base(id, siloAddress, true, loggerFactory)
        {
            if (strProviderName == null)
            {
                throw new ArgumentNullException("runtime", "PersistentStreamPullingAgent: strProviderName should not be null");
            }

            QueueId                   = queueId;
            streamProviderName        = strProviderName;
            pubSub                    = streamPubSub;
            this.streamFilter         = streamFilter;
            pubSubCache               = new Dictionary <InternalStreamId, StreamConsumerCollection>();
            this.options              = options;
            this.queueAdapter         = queueAdapter ?? throw new ArgumentNullException(nameof(queueAdapter));
            this.streamFailureHandler = streamFailureHandler ?? throw new ArgumentNullException(nameof(streamFailureHandler));;
            this.queueAdapterCache    = queueAdapterCache;
            numMessages               = 0;

            logger = loggerFactory.CreateLogger($"{this.GetType().Namespace}.{streamProviderName}");
            logger.LogInformation(
                (int)ErrorCode.PersistentStreamPullingAgent_01,
                "Created {Name} {Id} for Stream Provider {StreamProvider} on silo {Silo} for Queue {Queue}.",
                GetType().Name,
                ((ISystemTargetBase)this).GrainId.ToString(),
                streamProviderName,
                Silo,
                QueueId.ToStringWithHashCode());
            numReadMessagesCounter = CounterStatistic.FindOrCreate(new StatisticName(StatisticNames.STREAMS_PERSISTENT_STREAM_NUM_READ_MESSAGES, StatisticUniquePostfix));
            numSentMessagesCounter = CounterStatistic.FindOrCreate(new StatisticName(StatisticNames.STREAMS_PERSISTENT_STREAM_NUM_SENT_MESSAGES, StatisticUniquePostfix));
        }
Esempio n. 11
0
 internal LocalReminderService(
     Silo silo,
     IReminderTable reminderTable,
     TimeSpan initTimeout,
     ILoggerFactory loggerFactory,
     IAsyncTimerFactory asyncTimerFactory)
     : base(SystemTargetGrainId.CreateGrainServiceGrainId(GrainInterfaceUtils.GetGrainClassTypeCode(typeof(IReminderService)), null, silo.SiloAddress), silo, loggerFactory)
 {
     localReminders         = new Dictionary <ReminderIdentity, LocalReminderData>();
     this.reminderTable     = reminderTable;
     this.initTimeout       = initTimeout;
     this.asyncTimerFactory = asyncTimerFactory;
     localTableSequence     = 0;
     tardinessStat          = AverageTimeSpanStatistic.FindOrCreate(StatisticNames.REMINDERS_AVERAGE_TARDINESS_SECONDS);
     IntValueStatistic.FindOrCreate(StatisticNames.REMINDERS_NUMBER_ACTIVE_REMINDERS, () => localReminders.Count);
     ticksDeliveredStat    = CounterStatistic.FindOrCreate(StatisticNames.REMINDERS_COUNTERS_TICKS_DELIVERED);
     startedTask           = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
     this.logger           = loggerFactory.CreateLogger <LocalReminderService>();
     this.listRefreshTimer = asyncTimerFactory.Create(Constants.RefreshReminderList, "ReminderService.ReminderListRefresher");
 }
Esempio n. 12
0
        private void SendRequestMessage(GrainReference target, Message message, IResponseCompletionSource context, InvokeMethodOptions options)
        {
            message.InterfaceType    = target.InterfaceType;
            message.InterfaceVersion = target.InterfaceVersion;
            var targetGrainId = target.GrainId;
            var oneWay        = (options & InvokeMethodOptions.OneWay) != 0;

            message.SendingGrain      = CurrentActivationAddress.Grain;
            message.SendingActivation = CurrentActivationAddress.Activation;
            message.TargetGrain       = targetGrainId;

            if (SystemTargetGrainId.TryParse(targetGrainId, out var systemTargetGrainId))
            {
                // If the silo isn't be supplied, it will be filled in by the sender to be the gateway silo
                message.TargetSilo       = systemTargetGrainId.GetSiloAddress();
                message.TargetActivation = ActivationId.GetDeterministic(targetGrainId);
            }

            if (message.IsExpirableMessage(this.clientMessagingOptions.DropExpiredMessages))
            {
                // don't set expiration for system target messages.
                message.TimeToLive = this.clientMessagingOptions.ResponseTimeout;
            }

            if (!oneWay)
            {
                var callbackData = new CallbackData(this.sharedCallbackData, context, message);
                callbacks.TryAdd(message.Id, callbackData);
            }
            else
            {
                context?.Complete();
            }

            if (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace("Send {0}", message);
            }
            MessageCenter.SendMessage(message);
        }
Esempio n. 13
0
 private static SystemTargetGrainId CreateId(ILocalSiloDetails localSiloDetails)
 {
     return(SystemTargetGrainId.Create(Constants.SystemMembershipTableType, SiloAddress.New(localSiloDetails.SiloAddress.Endpoint, 0)));
 }