private static bool HasConditional(string content, string[] conditionals, string sign, out ConditionalResult result) { result = new ConditionalResult(); foreach (var _keyword in conditionals) { string keyword = $" {_keyword} "; if (content.IndexOf(keyword) == -1) { continue; } var index = content.IndexOf(keyword); while (index != -1) { if (!FiMHelper.IsIndexInsideString(content, index)) { result.Keyword = keyword; result.Sign = sign; result.Index = index; return(true); } var newIndex = content.IndexOf(keyword, index); if (newIndex == index) { break; } index = newIndex; } } return(false); }
/// <summary> /// This is the main entry point for your service's partition replica. /// RunAsync executes when the primary replica for this partition has write status. /// </summary> /// <param name="cancellationToken">Canceled when Service Fabric terminates this partition's replica.</param> protected override async Task RunAsync(CancellationToken cancellationToken) { var queryModelBuilder = GetQueryModelBuilder(); var queue = await StateManager.GetOrAddAsync <IReliableQueue <string> >("queryModelBuilderQueue"); var count = (int)await queue.GetCountAsync(); if (count > 0) { _semaphore.Release(count); } while (true) { cancellationToken.ThrowIfCancellationRequested(); using (ITransaction tx = StateManager.CreateTransaction()) { ConditionalResult <string> dequeueReply = await queue.TryDequeueAsync(tx); if (dequeueReply.HasValue) { string message = dequeueReply.Value; await queryModelBuilder.Handle(CqrsApplication.GetService <IDeserializer>().CreateEvent(JObject.Parse(message))); await tx.CommitAsync(); } } await _semaphore.WaitAsync(cancellationToken); } }
protected async Task <Processor> GetProcessorAsync(string ProcessorName, ITransaction tx = null) { ITransaction _trx = tx ?? this.Svc.StateManager.CreateTransaction(); Processor processor; ConditionalResult <Processor> cResult = await this.Svc.ProcessorStateStore.TryGetValueAsync(_trx, ProcessorName); if (cResult.HasValue) { processor = cResult.Value; } else { processor = null; } if (null == tx) { await _trx.CommitAsync(); _trx.Dispose(); } return(processor); }
public async Task <HttpResponseMessage> GetFullTelemetryFrame(int id) { if (id == 0) { return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "No Data")); } var dataCollection = await _reliableStateManager.GetOrAddAsync <IReliableDictionary <int, Telemetry> >(String.Format("VehicleId-{0}", id)); using (ITransaction transaction = _reliableStateManager.CreateTransaction()) { ConditionalResult <Telemetry> result = await dataCollection.TryGetValueAsync(transaction, 0); if (result.HasValue) { HttpResponseMessage httpResponseMessage = Request.CreateResponse <Telemetry>(result.Value); httpResponseMessage.StatusCode = HttpStatusCode.Found; return(httpResponseMessage); } else { HttpResponseMessage httpResponseMessage = Request.CreateResponse(); httpResponseMessage.StatusCode = HttpStatusCode.NotFound; return(httpResponseMessage); } } }
public static async Task <StateManagerLease> GetOrCreateAsync( IReliableStateManager StateManager, IReliableDictionary <string, string> StateDictionary, string EntryName, string partitionId) { using (ITransaction tx = StateManager.CreateTransaction()) { StateManagerLease lease; // if something has been saved before load it ConditionalResult <string> cResults = await StateDictionary.TryGetValueAsync(tx, EntryName); if (cResults.HasValue) { lease = FromJsonString(cResults.Value); lease.m_StateDictionary = StateDictionary; lease.m_StateManager = StateManager; } else { // if not create new lease = new StateManagerLease(StateManager, StateDictionary, EntryName, partitionId); } await tx.CommitAsync(); return(lease); } }
public async Task <Processor> Stop([FromUri] string ProcessorName) { string[] validationErrors = Processor.ValidateProcessName(ProcessorName); if (null != validationErrors) { Utils.ThrowHttpError(validationErrors); } Processor existing; using (ITransaction tx = this.Svc.StateManager.CreateTransaction()) { // do we have it? ConditionalResult <Processor> cResults = await this.Svc.ProcessorStateStore.TryGetValueAsync(tx, ProcessorName); if (!cResults.HasValue) { Utils.ThrowHttpError(string.Format("processor with the name {0} does not exists", ProcessorName)); } existing = cResults.Value; if (existing.IsOkToQueueOperation()) { Utils.ThrowHttpError( string.Format("Processor with the name {0} not valid for this operation", ProcessorName, existing.ProcessorStatusString)); } existing.ProcessorStatus |= ProcessorStatus.PendingStop; existing = await this.Svc.ProcessorStateStore.AddOrUpdateAsync( tx, existing.Name, existing, (name, proc) => { proc.SafeUpdate(existing); return(proc); }); await this.Svc.ProcessorOperationsQueue.EnqueueAsync( tx, new ProcessorOperation() { OperationType = ProcessorOperationType.Stop, ProcessorName = ProcessorName }); await tx.CommitAsync(); ServiceEventSource.Current.Message(string.Format("Queued stop command for processor {0} ", existing.Name)); } return(existing); }
public async Task <HttpResponseMessage> TelemetryIngest([FromBody] Telemetry telemetry) { if (telemetry == null) { return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "No Data")); } var dataCollection = await _reliableStateManager.GetOrAddAsync <IReliableDictionary <int, Telemetry> >(String.Format("VehicleId-{0}", telemetry.Id)); bool fullFrameIngest = (telemetry.MessageNumber % 10 == 0) || (telemetry.MessageNumber == 1); Telemetry fullTelemetry = new Telemetry(); if (fullFrameIngest) { fullTelemetry = telemetry; } else { using (ITransaction transaction = _reliableStateManager.CreateTransaction()) { ConditionalResult <Telemetry> result = await dataCollection.TryGetValueAsync(transaction, 0); if (result.HasValue) { fullTelemetry = result.Value; } } fullTelemetry.Speed = telemetry.Speed ?? fullTelemetry.Speed; fullTelemetry.EmergencySituation = telemetry.EmergencySituation ?? fullTelemetry.EmergencySituation; fullTelemetry.PoIType = telemetry.PoIType ?? fullTelemetry.PoIType; fullTelemetry.Latitude = telemetry.Latitude == 0 ? fullTelemetry.Latitude : telemetry.Latitude; fullTelemetry.Longitude = telemetry.Longitude == 0 ? fullTelemetry.Longitude : telemetry.Longitude; } using (ITransaction transaction = _reliableStateManager.CreateTransaction()) { ConditionalResult <Telemetry> result = await dataCollection.TryGetValueAsync(transaction, 0); if (!result.HasValue) { await dataCollection.TryAddAsync(transaction, 0, fullTelemetry); } else { await dataCollection.AddOrUpdateAsync(transaction, 0, fullTelemetry, (int key, Telemetry data) => fullTelemetry); } await transaction.CommitAsync(); } //TODO: Add EventHub Ingest return(Request.CreateResponse(HttpStatusCode.Created)); }
public async Task JoinClusterAsync(string username, string clusterName) { if (String.IsNullOrWhiteSpace(username)) { throw new ArgumentNullException("username"); } if (String.IsNullOrWhiteSpace(clusterName)) { throw new ArgumentNullException("clusterName"); } IReliableDictionary <string, Cluster> clusterDictionary = await this.reliableStateManager.GetOrAddAsync <IReliableDictionary <string, Cluster> >(ClusterDictionaryName); int userPort; string clusterAddress; using (ITransaction tx = this.reliableStateManager.CreateTransaction()) { ConditionalResult <Cluster> result = await clusterDictionary.TryGetValueAsync(tx, clusterName, LockMode.Update); if (!result.HasValue) { throw new KeyNotFoundException(); } Cluster cluster = result.Value; // make sure the cluster is ready if (cluster.Status != ClusterStatus.Ready) { throw new InvalidOperationException(); // need a better exception here } // make sure the cluster isn't about to be deleted. if ((DateTimeOffset.UtcNow - cluster.CreatedOn.ToUniversalTime()) > (this.Config.MaxClusterUptime - TimeSpan.FromMinutes(5))) { throw new InvalidOperationException(); // need a better exception here } userPort = cluster.Ports.First(port => !cluster.Users.Select(x => x.Port).Contains(port)); clusterAddress = cluster.Address; cluster.Users.Add(new ClusterUser() { Name = username, Port = userPort }); await clusterDictionary.SetAsync(tx, clusterName, cluster); await tx.CommitAsync(); } // send email to user with cluster info }
public async Task <Processor> Add([FromUri] string ProcessorName, [FromBody] Processor processor) { processor.Name = ProcessorName; string[] validationErrors = processor.Validate(); if (null != validationErrors) { Utils.ThrowHttpError(validationErrors); } processor.ProcessorStatus = ProcessorStatus.New; using (ITransaction tx = this.Svc.StateManager.CreateTransaction()) { // do we have it? ConditionalResult <Processor> cResults = await this.Svc.ProcessorStateStore.TryGetValueAsync(tx, processor.Name); if (cResults.HasValue) { Utils.ThrowHttpError( string.Format("Processor with the name {0} currently exists with status", processor.Name), string.Format( "Processor {0} is currently {1} and mapped to app {2}", cResults.Value.Name, cResults.Value.ProcessorStatus.ToString(), cResults.Value.ServiceFabricAppInstanceName)); } // save it await this.Svc.ProcessorStateStore.AddAsync(tx, processor.Name, processor); // create it it await this.Svc.ProcessorOperationsQueue.EnqueueAsync( tx, new ProcessorOperation() { OperationType = ProcessorOperationType.Add, ProcessorName = processor.Name }); await tx.CommitAsync(); ServiceEventSource.Current.Message(string.Format("Queued create for processor {0} ", processor.Name)); } return(processor); }
public async Task <List <ProcessorRuntimeStatus> > GetDetailedStatus([FromUri] string ProcessorName) { string[] validationErrors = Processor.ValidateProcessName(ProcessorName); if (null != validationErrors) { Utils.ThrowHttpError(validationErrors); } Processor processor; using (ITransaction tx = this.Svc.StateManager.CreateTransaction()) { // do we have it? ConditionalResult <Processor> cResults = await this.Svc.ProcessorStateStore.TryGetValueAsync(tx, ProcessorName); if (!cResults.HasValue) { Utils.ThrowHttpError(string.Format("Processor with the name {0} does not exist", ProcessorName)); } processor = cResults.Value; } ProcessorOperationHandlerFactory factory = new ProcessorOperationHandlerFactory(); ProcessorOperationHandlerBase operationHandler = factory.CreateHandler( this.Svc, new ProcessorOperation() { OperationType = ProcessorOperationType.RuntimeStatusCheck, ProcessorName = ProcessorName }); List <ProcessorRuntimeStatus> runtimeStatus = new List <ProcessorRuntimeStatus>(); Task <HttpResponseMessage>[] tasks = await operationHandler.ExecuteOperation <Task <HttpResponseMessage>[]>(null); await Task.WhenAll(tasks); foreach (Task <HttpResponseMessage> completedTask in tasks) { HttpResponseMessage httpResponse = completedTask.Result; if (!httpResponse.IsSuccessStatusCode) { Utils.ThrowHttpError("error aggregating status from processor partitions"); } runtimeStatus.Add(JsonConvert.DeserializeObject <ProcessorRuntimeStatus>(await httpResponse.Content.ReadAsStringAsync())); } return(runtimeStatus); }
public async Task <bool> IsItemInInventoryAsync(InventoryItemId itemId) { ServiceEventSource.Current.Message("checking item {0} to see if it is in inventory", itemId); IReliableDictionary <InventoryItemId, InventoryItem> inventoryItems = await this.stateManager.GetOrAddAsync <IReliableDictionary <InventoryItemId, InventoryItem> >(InventoryItemDictionaryName); PrintInventoryItems(inventoryItems); using (ITransaction tx = this.stateManager.CreateTransaction()) { ConditionalResult <InventoryItem> item = await inventoryItems.TryGetValueAsync(tx, itemId); return(item.HasValue); } }
public async Task <IHttpActionResult> Count() { IReliableDictionary <string, long> statsDictionary = await this.stateManager.GetOrAddAsync <IReliableDictionary <string, long> >("statsDictionary"); using (ITransaction tx = this.stateManager.CreateTransaction()) { ConditionalResult <long> result = await statsDictionary.TryGetValueAsync(tx, "Number of Words Processed"); if (result.HasValue) { return(this.Ok(result.Value)); } } return(this.Ok(0)); }
public ConditionalResult <TValue> TryRemove(ITransaction tx, TKey key, long version = -1) { var transaction = tx.GetTransaction(); var id = Interlocked.Increment(ref this.operationNumber); Operation undo; var dbTransaction = this.tables.CreateTransaction(); ConditionalResult <TValue> result; try { TValue initialValue; if (dbTransaction.Table.TryGetValue(key, out initialValue)) { undo = new SetOperation { Key = key, Value = initialValue, Id = id }; result = new ConditionalResult <TValue>(true, initialValue); } else { undo = NopOperation.Instance; result = new ConditionalResult <TValue>(); } } catch { dbTransaction.Rollback(); dbTransaction.Dispose(); throw; } var redo = new RemoveOperation { Key = key, Id = id }; this.PerformOperation <object>( id, new OperationContext { DatabaseTransaction = dbTransaction, ReplicatorTransaction = transaction }, undo, redo); return(result); }
private async Task <Processor> GetAssignedProcessorFromState() { Processor processor = null; IReliableDictionary <string, string> dict = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, string> >(DefDictionary); using (ITransaction tx = this.StateManager.CreateTransaction()) { ConditionalResult <string> cResult = await dict.TryGetValueAsync(tx, AssignedProcessorEntryName); if (cResult.HasValue) { processor = Processor.FromJsonString(cResult.Value); } await tx.CommitAsync(); } return(processor); }
public ConditionalResult <T> Get <T>(string key) where T : class { var cachedObject = _cache.Get(key); if (cachedObject?.Value != null) { if (_cloningProvider.RequireCloning(cachedObject.Value.GetType())) { return(ConditionalResult.CreateSuccessful(_cloningProvider.Clone(cachedObject.Value as T))); } return(ConditionalResult.CreateSuccessful(cachedObject.Value as T)); } return(ConditionalResult.CreateFailure <T>()); }
async Task <IEnumerable <string> > ISimpleStatefulService.GetStrings() { var queue = await StateManager.GetOrAddAsync <IReliableQueue <string> >(QueueName); var strings = new List <string>(25); using (var tx = StateManager.CreateTransaction()) { ConditionalResult <string> s = await queue.TryDequeueAsync(tx); while (s.HasValue) { strings.Add(s.Value); s = await queue.TryDequeueAsync(tx); } await tx.CommitAsync(); } return(strings); }
/// <summary> /// Tries to add the given quantity to the inventory item with the given ID without going over the maximum quantity allowed for an item. /// </summary> /// <param name="itemId"></param> /// <param name="quantity"></param> /// <returns>The quantity actually added to the item.</returns> public async Task <int> AddStockAsync(InventoryItemId itemId, int quantity) { IReliableDictionary <InventoryItemId, InventoryItem> inventoryItems = await this.stateManager.GetOrAddAsync <IReliableDictionary <InventoryItemId, InventoryItem> >(InventoryItemDictionaryName); int quantityAdded = 0; ServiceEventSource.Current.ServiceMessage(this, "Received add stock request. Item: {0}. Quantity: {1}.", itemId, quantity); using (ITransaction tx = this.stateManager.CreateTransaction()) { // Try to get the InventoryItem for the ID in the request. ConditionalResult <InventoryItem> item = await inventoryItems.TryGetValueAsync(tx, itemId); // We can only update the stock for InventoryItems in the system - we are not adding new items here. if (item.HasValue) { // Update the stock quantity of the item. // This only updates the copy of the Inventory Item that's in local memory here; // It's not yet saved in the dictionary. quantityAdded = item.Value.AddStock(quantity); // We have to store the item back in the dictionary in order to actually save it. // This will then replicate the updated item for await inventoryItems.SetAsync(tx, item.Value.Id, item.Value); } // nothing will happen unless we commit the transaction! await tx.CommitAsync(); ServiceEventSource.Current.ServiceMessage( this, "Add stock complete. Item: {0}. Added: {1}. Total: {2}", item.Value.Id, quantityAdded, item.Value.AvailableStock); } return(quantityAdded); }
public async Task <Processor> Get([FromUri] string ProcessorName) { string[] validationErrors = Processor.ValidateProcessName(ProcessorName); if (null != validationErrors) { Utils.ThrowHttpError(validationErrors); } using (ITransaction tx = this.Svc.StateManager.CreateTransaction()) { // do we have it? ConditionalResult <Processor> cResults = await this.Svc.ProcessorStateStore.TryGetValueAsync(tx, ProcessorName); if (!cResults.HasValue) { Utils.ThrowHttpError(string.Format("Processor with the name {0} does not exist", ProcessorName)); } return(cResults.Value); } }
/// <summary> /// This is the main entry point for your service's partition replica. /// RunAsync executes when the primary replica for this partition has write status. /// </summary> /// <param name="cancellationToken">Canceled when Service Fabric terminates this partition's replica.</param> protected override async Task RunAsync(CancellationToken cancellationToken) { var queue = await StateManager.GetOrAddAsync <IReliableQueue <string> >("eventBusQueue"); // We use the ServiceFabricEventBus as our way of dispatching in this service. // The class has all the registered builders and can locate them through the ServiceClient. var eventBus = new ServiceFabricEventBus(); Handlers.QueryModelBuilders.ToList().ForEach(eventBus.RegisterBuilder); var deserializer = new Deserializer(); var count = (int)await queue.GetCountAsync(); if (count > 0) { _semaphore.Release(count); } while (true) { cancellationToken.ThrowIfCancellationRequested(); using (ITransaction tx = StateManager.CreateTransaction()) { ConditionalResult <string> dequeueReply = await queue.TryDequeueAsync(tx); if (dequeueReply.HasValue) { string message = dequeueReply.Value; await eventBus.Dispatch(deserializer.CreateEvent(JObject.Parse(message))); await tx.CommitAsync(); } } await _semaphore.WaitAsync(cancellationToken); } }
public static bool GetConditional(string content, out ConditionalResult result) { if (HasConditional(content, And, "&&", out result)) { return(true); } if (HasConditional(content, Or, "||", out result)) { return(true); } if (HasConditional(content, LessThanEqual, "<=", out result)) { return(true); } if (HasConditional(content, GreaterThanEqual, ">=", out result)) { return(true); } if (HasConditional(content, GreaterThan, ">", out result)) { return(true); } if (HasConditional(content, LessThan, "<", out result)) { return(true); } if (HasConditional(content, Not, "!=", out result)) { return(true); } if (HasConditional(content, Equal, "==", out result)) { return(true); } return(false); }
/// <inheritdoc/> public ConditionalResult <T> Get <T>(string key) where T : class { CachedObject cachedObject = _cache.Get(key); if (cachedObject == null) { return(ConditionalResult.CreateFailure <T>()); } if (cachedObject.Value == null) { return(ConditionalResult.CreateSuccessful <T>(null)); } var castedValue = cachedObject.Value as T; if (castedValue == null) { return(ConditionalResult.CreateFailure <T>()); } return(ConditionalResult.CreateSuccessful(castedValue)); }
/// <summary> /// Drains the queue of completed restock requests sends them to InventoryService. /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> protected override async Task RunAsync(CancellationToken cancellationToken) { IReliableQueue <RestockRequest> completedRequests = await this.StateManager.GetOrAddAsync <IReliableQueue <RestockRequest> >(CompletedRequestsQueueName); while (!cancellationToken.IsCancellationRequested) { using (ITransaction tx = this.StateManager.CreateTransaction()) { ConditionalResult <RestockRequest> result = await completedRequests.TryDequeueAsync(tx, TxTimeout, cancellationToken); if (result.HasValue) { ServiceUriBuilder builder = new ServiceUriBuilder(InventoryServiceName); IInventoryService inventoryService = ServiceProxy.Create <IInventoryService>(result.Value.ItemId.GetPartitionKey(), builder.ToUri()); await inventoryService.AddStockAsync(result.Value.ItemId, result.Value.Quantity); ServiceEventSource.Current.ServiceMessage( this, "Adding stock to inventory service. ID: {0}. Quantity: {1}", result.Value.ItemId, result.Value.Quantity); } // 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(); } await Task.Delay(CompletedRequestsBatchInterval, cancellationToken); } }
private async Task workLoopAsync() { int nLongDequeueWaitTimeMs = 20 * 1000; int nShortDequeueWaitTimeMs = 2 * 1000; int nNoQueueWaitTimeMS = 5 * 1000; int nPauseCheckMs = 5 * 1000; while (this.m_KeepWorking) { // pause check while (this.m_Pause) { await Task.Delay(nPauseCheckMs); } // take the queue KeyValuePair <string, IReliableQueue <Wi> > kvp = this.m_WorkManager.m_QueueManager.TakeQueueAsync(); if (null == kvp.Value) // no queue to work on. { // this will only happen if executers # are > than queues // usually a situation that should resolve it self. // well by the following logic this.m_WorkManager.m_TraceWriter.TraceMessage( string.Format("Executer {0} found no q and will sleep for {1}", this.m_WorkerExecuterId, nNoQueueWaitTimeMS)); await this.FinilizeQueueWork(0, null, null); // check removal await Task.Delay(nNoQueueWaitTimeMS); // sleep as there is no point of retrying right away. continue; } // got Q IReliableQueue <Wi> q = kvp.Value; string qName = kvp.Key; int nCurrentMessage = 0; try { while (this.m_KeepWorking & !this.m_Pause) { nCurrentMessage++; // processed the # of messages? if (nCurrentMessage > this.m_WorkManager.YieldQueueAfter) { break; //-> to finally } // as long as we have other queues. we need to have a short wait time int ActualTimeOut = this.m_WorkManager.m_QueueManager.Count > this.m_WorkManager.m_Executers.Count ? nShortDequeueWaitTimeMs : nLongDequeueWaitTimeMs; using (ITransaction tx = this.m_WorkManager.StateManager.CreateTransaction()) { ConditionalResult <Wi> cResults = await q.TryDequeueAsync( tx, TimeSpan.FromMilliseconds(ActualTimeOut), CancellationToken.None); if (cResults.HasValue) { Handler handler = this.m_WorkManager.GetHandlerForQueue(qName); Wi wi = await handler.HandleWorkItem(cResults.Value); if (null != wi) // do we have an enqueue request? { await q.EnqueueAsync(tx, wi); } await tx.CommitAsync(); this.m_WorkManager.DecreaseBufferedWorkItems(); } else { break; // -> to finally } } } } catch (TimeoutException to) { /* Queue is locked for enqueues */ this.m_WorkManager.m_TraceWriter.TraceMessage( string.Format("Executer Dequeue Timeout after {0}: {1}", nLongDequeueWaitTimeMs, to.Message)); break; //-> to finally } catch (AggregateException aex) { AggregateException ae = aex.Flatten(); this.m_WorkManager.m_TraceWriter.TraceMessage( string.Format( "Executer encountered fatel error and will exit E:{0} StackTrace:{1}", ae.GetCombinedExceptionMessage(), ae.GetCombinedExceptionStackTrace())); throw; } catch (Exception E) { this.m_WorkManager.m_TraceWriter.TraceMessage( string.Format("Executer encountered fatel error and will exit E:{0} StackTrace:{1}", E.Message, E.StackTrace)); throw; } finally { await this.FinilizeQueueWork(nCurrentMessage, qName, q); } } this.m_WorkManager.m_TraceWriter.TraceMessage(string.Format("Worker {0} exited loop", this.m_WorkerExecuterId)); }
protected override async Task RunAsync(CancellationToken cancellationToken) { this.SetProcessorAppInstanceDefaults(); // subscribe to configuration changes this.ServiceInitializationParameters.CodePackageActivationContext.ConfigurationPackageModifiedEvent += this.CodePackageActivationContext_ConfigurationPackageModifiedEvent; this.ProcessorStateStore = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, Processor> >(ProcessorDefinitionStateDictionaryName); this.ProcessorOperationsQueue = await this.StateManager.GetOrAddAsync <IReliableQueue <ProcessorOperation> >(OperationQueueName); this.ProcessorOperationFactory = new ProcessorOperationHandlerFactory(); ProcessorOperation processorOperation = null; // pump and execute ProcessorPperation from the queue while (!cancellationToken.IsCancellationRequested) { using (ITransaction tx = this.StateManager.CreateTransaction()) { try { ConditionalResult <ProcessorOperation> result = await this.ProcessorOperationsQueue.TryDequeueAsync( tx, TimeSpan.FromMilliseconds(1000), cancellationToken); if (result.HasValue) { processorOperation = result.Value; ProcessorOperationHandlerBase handler = this.ProcessorOperationFactory.CreateHandler(this, processorOperation); await handler.RunOperation(tx); await tx.CommitAsync(); } } catch (TimeoutException toe) { ServiceEventSource.Current.Message( string.Format("Controller service encountered timeout in a work operations de-queue process {0} and will try again", toe.StackTrace)); } catch (AggregateException aex) { AggregateException ae = aex.Flatten(); string sError = string.Empty; if (null == processorOperation) { sError = string.Format( "Event Processor Management Service encountered an error processing Processor-Operation {0} {1} and will terminate replica", ae.GetCombinedExceptionMessage(), ae.GetCombinedExceptionStackTrace()); } else { sError = string.Format( "Event Processor Management Service encountered an error processing Processor-opeartion {0} against {1} Error {2} stack trace {3} and will terminate replica", processorOperation.OperationType.ToString(), processorOperation.ProcessorName, ae.GetCombinedExceptionMessage(), ae.GetCombinedExceptionStackTrace()); } ServiceEventSource.Current.ServiceMessage(this, sError); throw; } } } }
/// <inheritdoc/> public ConditionalResult <T> Get <T>(string key) where T : class { return(ConditionalResult.CreateFailure <T>()); }
/// <summary> /// Removes the given quantity of stock from an in item in the inventory. /// </summary> /// <param name="request"></param> /// <returns>int: Returns the quantity removed from stock.</returns> public async Task <int> RemoveStockAsync(InventoryItemId itemId, int quantity, CustomerOrderActorMessageId amId) { ServiceEventSource.Current.ServiceMessage(this, "inside remove stock {0}|{1}", amId.GetHashCode(), amId.GetHashCode()); IReliableDictionary <InventoryItemId, InventoryItem> inventoryItems = await this.stateManager.GetOrAddAsync <IReliableDictionary <InventoryItemId, InventoryItem> >(InventoryItemDictionaryName); IReliableDictionary <CustomerOrderActorMessageId, DateTime> recentRequests = await this.stateManager.GetOrAddAsync <IReliableDictionary <CustomerOrderActorMessageId, DateTime> >(ActorMessageDictionaryName); IReliableDictionary <CustomerOrderActorMessageId, Tuple <InventoryItemId, int> > requestHistory = await this.stateManager.GetOrAddAsync <IReliableDictionary <CustomerOrderActorMessageId, Tuple <InventoryItemId, int> > >(RequestHistoryDictionaryName); int removed = 0; ServiceEventSource.Current.ServiceMessage(this, "Received remove stock request. Item: {0}. Quantity: {1}.", itemId, quantity); using (ITransaction tx = this.stateManager.CreateTransaction()) { //first let's see if this is a duplicate request ConditionalResult <DateTime> previousRequest = await recentRequests.TryGetValueAsync(tx, amId); if (!previousRequest.HasValue) { //first time we've seen the request or it was a dupe from so long ago we have forgotten // Try to get the InventoryItem for the ID in the request. ConditionalResult <InventoryItem> item = await inventoryItems.TryGetValueAsync(tx, itemId); // We can only remove stock for InventoryItems in the system. if (item.HasValue) { // Update the stock quantity of the item. // This only updates the copy of the Inventory Item that's in local memory here; // It's not yet saved in the dictionary. removed = item.Value.RemoveStock(quantity); // We have to store the item back in the dictionary in order to actually save it. // This will then replicate the updated item await inventoryItems.SetAsync(tx, itemId, item.Value); //we also have to make a note that we have returned this result, so that we can protect //ourselves from stale or duplicate requests that come back later await requestHistory.SetAsync(tx, amId, new Tuple <InventoryItemId, int>(itemId, removed)); ServiceEventSource.Current.ServiceMessage( this, "Removed stock complete. Item: {0}. Removed: {1}. Remaining: {2}", item.Value.Id, removed, item.Value.AvailableStock); } } else { //this is a duplicate request. We need to send back the result we already came up with and hope they get it this time //find the previous result and send it back ConditionalResult <Tuple <InventoryItemId, int> > previousResponse = await requestHistory.TryGetValueAsync(tx, amId); if (previousResponse.HasValue) { removed = previousResponse.Value.Item2; ServiceEventSource.Current.ServiceMessage( this, "Retrieved previous response for request {0}, from {1}, for Item {2} and quantity {3}", amId, previousRequest.Value, previousResponse.Value.Item1, previousResponse.Value.Item2); } else { //we've seen the request before but we don't have a record for what we responded, inconsistent state ServiceEventSource.Current.ServiceMessage( this, "Inconsistent State: recieved duplicate request {0} but don't have matching response in history", amId); this.ServicePartition.ReportFault(System.Fabric.FaultType.Transient); } //note about duplicate Requests: technically if a duplicate request comes in and we have //sufficient invintory to return more now that we did previously, we could return more of the order and decrement //the difference to reduce the total number of round trips. This optimization is not currently implemented } //always update the datetime for the given request await recentRequests.SetAsync(tx, amId, DateTime.UtcNow); // nothing will happen unless we commit the transaction! ServiceEventSource.Current.Message("Committing Changes in Inventory Service"); await tx.CommitAsync(); ServiceEventSource.Current.Message("Inventory Service Changes Committed"); } ServiceEventSource.Current.Message("Removed {0} of item {1}", removed, itemId); return(removed); }
protected override async Task RunAsync(CancellationToken cancellationToken) { ServiceEventSource.Current.RunAsyncInvoked(ServiceEventSourceName); IReliableQueue <string> inputQueue = await this.StateManager.GetOrAddAsync <IReliableQueue <string> >("inputQueue"); IReliableDictionary <string, long> wordCountDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, long> >("wordCountDictionary"); IReliableDictionary <string, long> statsDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, long> >("statsDictionary"); while (true) { cancellationToken.ThrowIfCancellationRequested(); try { using (ITransaction tx = this.StateManager.CreateTransaction()) { ConditionalResult <string> dequeuReply = await inputQueue.TryDequeueAsync(tx); if (dequeuReply.HasValue) { string word = dequeuReply.Value; long count = await wordCountDictionary.AddOrUpdateAsync( tx, word, 1, (key, oldValue) => oldValue + 1); long numberOfProcessedWords = await statsDictionary.AddOrUpdateAsync( tx, "Number of Words Processed", 1, (key, oldValue) => oldValue + 1); long queueLength = await inputQueue.GetCountAsync(tx); await tx.CommitAsync(); ServiceEventSource.Current.RunAsyncStatus( this.ServicePartition.PartitionInfo.Id, numberOfProcessedWords, queueLength, word, count); } } await Task.Delay(TimeSpan.FromMilliseconds(100), cancellationToken); } catch (TimeoutException) { //Service Fabric uses timeouts on collection operations to prevent deadlocks. //If this exception is thrown, it means that this transaction was waiting the default //amount of time (4 seconds) but was unable to acquire the lock. In this case we simply //retry after a random backoff interval. You can also control the timeout via a parameter //on the collection operation. Thread.Sleep(TimeSpan.FromSeconds(new Random().Next(100, 300))); continue; } catch (Exception exception) { //For sample code only: simply trace the exception. ServiceEventSource.Current.MessageEvent(exception.ToString()); } } }