Beispiel #1
0
        // IRemindable Interface Implementation
        public async Task ReceiveReminderAsync(string reminderName, byte[] context, TimeSpan dueTime, TimeSpan period)
        {
            var error   = "";
            var handler = HandlersFactory.GetProfilerHandler(SettingService);

            handler.Start(LOG_TAG, "ReceiveReminderAsync", GetActorProperties());

            try
            {
                handler.Info("Reminder " + reminderName);
                var state = await this.StateManager.GetStateAsync <EntityActorState>(ActorStatePropertyName);

                EntityTransaction transaction = (EntityTransaction)ByteArrayToObject(context);
                if (transaction == null)
                {
                    handler.Info("Transaction is null");
                }

                switch (reminderName)
                {
                case ReprocessReminder:
                {
                    // Unregister the reminder so the actor will be garbage collected
                    IActorReminder reminder = this.GetReminder(ReprocessReminder);
                    await this.UnregisterReminderAsync(reminder);

                    // Process this transaction
                    if (transaction.TransactionType == TransactionTypes.Purchase)
                    {
                        state.Purchases++;
                        state.SoldItems += transaction.SoldItems;
                        state.Revenue   += transaction.Revenue;
                        state.Tax       += transaction.Tax;
                        state.Shipping  += transaction.Shipping;
                    }
                    else if (transaction.TransactionType == TransactionTypes.Cancellation)
                    {
                        state.Cancellations++;
                        state.SoldItems -= transaction.SoldItems;
                        state.Revenue   -= transaction.Revenue;
                        state.Tax       -= transaction.Tax;
                        state.Shipping  -= transaction.Shipping;
                    }

                    // Make sure the state is saved
                    await SetEntityStateAsync(state);

                    // Publish an event that we are done processing
                    // Right now it is useless
                    // It is an excercise to see how events work
                    var ev = GetEvent <IEntityActorEvents>();
                    ev.MeasuresRecalculated(await GetEntity(), state.Purchases, state.Cancellations, state.SoldItems, state.Revenue, state.Tax, state.Shipping);

                    // If available, process the parent
                    var parent = await GetParent();

                    if (parent != null)
                    {
                        handler.Info("Parent actor type " + parent.Type);
                        IEntityActor parentActor = ActorLocationService.Create <IEntityActor>(parent.GetPartitionKey(), ApplicationName);
                        await parentActor.Process(transaction);
                    }

                    return;
                }

                default:
                {
                    // We should never arrive here normally. The system won't call reminders that don't exist.
                    // But for our own sake in case we add a new reminder somewhere and forget to handle it, this will remind us.
                    handler.Info("Unknown reminder: " + reminderName);
                    return;
                }
                }
            }
            catch (Exception ex)
            {
                error = ex.Message;
            }
            finally
            {
                handler.Stop(error);
            }
        }
Beispiel #2
0
        /// <summary>
        /// This is the main entry point for your service replica.
        /// This method executes when this replica of your service becomes primary and has write status.
        /// </summary>
        /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param>
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            // Gets (or creates) a replicated dictionary called "myDictionary" in this partition.
            var requests = await this.StateManager.GetOrAddAsync <IReliableQueue <EntityTransaction> >(ProcessQueueName);

            try
            {
                // This partition's replica continues processing until the replica is terminated.
                while (!cancellationToken.IsCancellationRequested)
                {
                    using (var tx = this.StateManager.CreateTransaction())
                    {
                        var result = await requests.TryDequeueAsync(tx, TxTimeout, cancellationToken);

                        if (result.HasValue)
                        {
                            var error   = "";
                            var handler = HandlersFactory.GetProfilerHandler(SettingService);
                            handler.Start(LOG_TAG, "AcquiredQueueItem", GetServiceProperties());

                            try
                            {
                                EntityTransaction transaction = result.Value;
                                handler.Info("Acquired item business key: " + transaction.BusinessKey + " - entity type: " + transaction.EntityType);

                                IActorLocationService locator     = ServiceFactory.GetActorLocationService();
                                IEntityActor          entityActor = locator.Create <IEntityActor>(new Entity(transaction.EntityType, transaction.BusinessKey).GetPartitionKey(), Constants.ApplicationName);
                                await entityActor.SubscribeAsync <IEntityActorEvents>(this);

                                await entityActor.Process(transaction);
                            }
                            catch (Exception ex)
                            {
                                error = ex.Message;
                            }
                            finally
                            {
                                handler.Stop(error);
                            }
                        }

                        // This commits the dequeue operations.
                        // If the request to add the stock to the inventory service throws, this commit will not execute
                        // and the items will remain on the queue, so we can be sure that we didn't dequeue items
                        // that didn't get saved successfully in the inventory service.
                        // However there is a very small chance that the stock was added to the inventory service successfully,
                        // but service execution stopped before reaching this commit (machine crash, for example).
                        await tx.CommitAsync();
                    }

                    // Pause for 2 second before continue processing.
                    await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken);
                }
            }
            catch (Exception ex)
            {
            }

            // Pause for 1 second before continue processing.
            await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
        }