async Task OnSay(Say msg, IOperationContext context) { RoomMember member; if (RoomMembers.TryGetValue(context.ReplyChannel, out member)) { RoomData room; if (Rooms.TryGetValue(member.RoomName, out room)) { var newEvent = new RoomEvent() { UserName = member.UserName, Text = msg.Text }; room.History.Add(newEvent); using (var tx = StateManager.CreateTransaction()) { await _roomsState.SetAsync(tx, room.Name, room); await tx.CommitAsync(); } room.Members.ForEach(m => m.UserChannel.Send(newEvent)); } } }
public async Task SetAsync(ITransaction tx, TKey key, TValue value) { if (reliableDictionary == null) { await InitializeReliableDictionary(); } await reliableDictionary.SetAsync(tx, key, value); }
public async Task <ConditionalValue <IReliableDictionary <TKey, TValue> > > TryCopyToReliableDictionary <TKey, TValue>(Dictionary <TKey, TValue> source, string targetKey, IReliableStateManager stateManager) where TKey : IComparable <TKey>, IEquatable <TKey> { var conditionalValue = await reliableStateManagerHelper.TryGetAsync <IReliableDictionary <TKey, TValue> >(stateManager, targetKey); if (!conditionalValue.HasValue) { return(new ConditionalValue <IReliableDictionary <TKey, TValue> >(false, null)); } IReliableDictionary <TKey, TValue> reliableDictionary = conditionalValue.Value; using (ITransaction tx = stateManager.CreateTransaction()) { await reliableDictionary.ClearAsync(); var tasks = new List <Task>(); foreach (var kvp in source) { tasks.Add(reliableDictionary.SetAsync(tx, kvp.Key, kvp.Value)); } Task.WaitAll(tasks.ToArray()); await tx.CommitAsync(); } return(new ConditionalValue <IReliableDictionary <TKey, TValue> >(true, reliableDictionary)); }
public async Task <IActionResult> Post(string distName, [FromBody] DistrictReport distReport) { try { IReliableDictionary <string, DistrictReport> distReports = await stateManager.GetOrAddAsync <IReliableDictionary <string, DistrictReport> >(CityReports); using (ITransaction tx = this.stateManager.CreateTransaction()) { await distReports.SetAsync(tx, distName, distReport); await tx.CommitAsync(); } return(this.Ok()); } catch (FabricNotPrimaryException ex) { return(new ContentResult { StatusCode = 410, Content = "The primary replica has moved. Please re-resolve the service." }); } catch (FabricException ex) { return(new ContentResult { StatusCode = 503, Content = "The service was unable to process the request. Please try again." }); } }
private async Task <Tuple <EventPosition, long> > GetOffsetAndEpochAsync(IReliableDictionary <string, string> offsetDictionary, IReliableDictionary <string, long> epochDictionary) { using (ITransaction tx = this.StateManager.CreateTransaction()) { ConditionalValue <string> offsetResult = await offsetDictionary.TryGetValueAsync(tx, "offset", LockMode.Default); ConditionalValue <long> epochResult = await epochDictionary.TryGetValueAsync(tx, "epoch", LockMode.Update); long newEpoch = epochResult.HasValue ? epochResult.Value + 1 : 0; // epoch is recorded each time the service fails over or restarts. await epochDictionary.SetAsync(tx, "epoch", newEpoch); await tx.CommitAsync(); EventPosition eventPosition; if (offsetResult.HasValue) { eventPosition = EventPosition.FromOffset(offsetResult.Value); } else { // TODO: make this configurable behaviour eventPosition = EventPosition.FromStart(); } return(new Tuple <EventPosition, long>(eventPosition, newEpoch)); } }
/// <summary> /// Sets the reference data for the passed in dictionary and id to the passed in data /// </summary> /// <returns></returns> public async Task SetReferenceDataAsync(string dictionaryName, int id, string data) { if (String.IsNullOrWhiteSpace(dictionaryName)) { throw new ArgumentNullException("dicationaryName"); } if (id < 0) { throw new ArgumentNullException("id"); } ServiceEventSource.Current.ServiceMessage(this.Context, "Request for dictionary: {0}, id: {1} to be updated to {2}", dictionaryName, id, data); IReliableDictionary <int, string> ignitionStateDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <int, string> >(dictionaryName); using (ITransaction tx = this.StateManager.CreateTransaction()) { await ignitionStateDictionary.SetAsync(tx, id, data); await tx.CommitAsync(); } ServiceEventSource.Current.ServiceMessage(this.Context, "Reference data update completed for dictionary: {0}, id: {1}, new data: {2}", dictionaryName, id, data); }
/// <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) { int removed = 0; 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); using (ITransaction tx = this.StateManager.CreateTransaction()) { ConditionalValue <InventoryItem> item = await inventoryItems.TryGetValueAsync(tx, itemId); if (item.HasValue) { removed = item.Value.RemoveStock(quantity); await inventoryItems.SetAsync(tx, itemId, item.Value); ServiceEventSource.Current.ServiceMessage( this, "Removed stock complete. Item: {0}. Removed: {1}. Remaining: {2}", item.Value.Id, removed, item.Value.AvailableStock); await tx.CommitAsync(); ServiceEventSource.Current.Message("Inventory Service Changes Committed"); ServiceEventSource.Current.Message("Removed {0} of item {1}", removed, itemId); } } return(removed); }
public async Task GenerateActors(IEnumerable <EventData> ehEvents, ITransaction tx) { if (ehEvents != null) { int batchCount = 0; List <string> tempRecords = new List <string>(); foreach (var ehEvent in ehEvents) { string message = Encoding.UTF8.GetString(ehEvent.Body.Array); ServiceEventSource.Current.ServiceMessage(this.serviceContext, $"Message Received: {message}"); string[] districtData = message.Split(','); string distId = districtData[2]; string distName = districtData[0]; string distTemp = districtData[1]; //create actor for each district ActorId districtId = new ActorId(distId); var distData = new DistrictData(distName, distTemp); IDistrictsActor districtsActor = ActorProxy.Create <IDistrictsActor>(districtId, this.DistrictsActorServiceUri); // districtsActor await districtsActor.ProcessDistData(distData); if (batchCount >= 0)// == 4) { var offset = ehEvent.SystemProperties.Offset; await offsetDictionary.SetAsync(tx, "offset", offset); } batchCount++; } } }
/// <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. ConditionalValue <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) { quantityAdded = item.Value.AddStock(quantity); await inventoryItems.SetAsync(tx, item.Value.Id, item.Value); } 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 <IActionResult> Post(string name, [FromBody] ValueViewModel value) { try { IReliableDictionary <string, string> dictionary = await this.stateManager.GetOrAddAsync <IReliableDictionary <string, string> >(ValuesDictionaryName); using (ITransaction tx = this.stateManager.CreateTransaction()) { await dictionary.SetAsync(tx, name, value.Value); await tx.CommitAsync(); } return(this.Ok()); } catch (FabricNotPrimaryException) { return(new ContentResult { StatusCode = 503, Content = "The primary replica has moved. Please re-resolve the service." }); } catch (FabricException) { return(new ContentResult { StatusCode = 503, Content = "The service was unable to process the request. Please try again." }); } }
public async Task GetAll() { MockApplicationLifetime appLifetime = new MockApplicationLifetime(); MockReliableStateManager stateManager = new MockReliableStateManager(); IReliableDictionary <string, DeviceEvent> store = await stateManager.GetOrAddAsync <IReliableDictionary <string, DeviceEvent> >(DataService.EventDictionaryName); Dictionary <string, DeviceEvent> expected = new Dictionary <string, DeviceEvent>(); expected.Add("device1", new DeviceEvent(DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(1)))); expected.Add("device2", new DeviceEvent(DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(2)))); using (ITransaction tx = stateManager.CreateTransaction()) { foreach (var item in expected) { await store.SetAsync(tx, item.Key, item.Value); } } DevicesController target = new DevicesController(stateManager, appLifetime); IActionResult result = await target.GetAsync(); Assert.True(result is OkObjectResult); IEnumerable <dynamic> actual = ((OkObjectResult)result).Value as IEnumerable <dynamic>; foreach (dynamic item in actual) { Assert.Equal <DateTimeOffset>(expected[item.Id].Timestamp, item.Timestamp); } }
public async Task ReportLoadAsync(ITransaction tx, Uri collectionName, IEnumerable <LoadMetric> metrics) { IReliableDictionary <string, List <LoadMetric> > metricDictionary = await this.stateManager.GetOrAddAsync <IReliableDictionary <string, List <LoadMetric> > >(this.metricStoreName); await metricDictionary.SetAsync(tx, collectionName.ToString(), metrics.ToList()); }
private async Task BackupSequenceNumberAsync() { if (_latestSequenceNumber > _backupSequenceNumber) { try { IReliableDictionary <string, string> streamOffsetDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, string> >(Names.EventHubOffsetDictionaryName); using (ITransaction tx = this.StateManager.CreateTransaction()) { await streamOffsetDictionary.SetAsync(tx, Names.HubStreamOffSetKey, _latestSequenceNumber.ToString()); await tx.CommitAsync(); } } catch (Exception exception) { string err = $"RouterService BackupSequenceNumberAsync met exception, event hub partition={_eventHubPartitionId}, " + $"exception type={exception.GetType().Name}, exception= {exception.Message}, at partition ={Context.PartitionId}."; //ServiceEventSource.Current.CriticalError("RouterService", err); } var suc = await SaveEventDataSequenceNumberAsync(); if (suc) { _backupSequenceNumber = _latestSequenceNumber; } } }
public async Task GetOrAddAsyncTestResultGetSet() { MetricReliableStateManager target = new MetricReliableStateManager( this.GetContext(), new JsonReliableStateSerializerResolver(), this.GetConfig(), new MockReliableStateManager()); IReliableDictionary <int, string> dictionary = await target.GetOrAddAsync <IReliableDictionary <int, string> >("test://dictionary"); string expected = "testvalue"; using (ITransaction tx = target.CreateTransaction()) { await dictionary.SetAsync(tx, 1, expected); await tx.CommitAsync(); } using (ITransaction tx = target.CreateTransaction()) { ConditionalValue <string> actual = await dictionary.TryGetValueAsync(tx, 1); Assert.AreEqual <string>(expected, actual.Value); } }
internal async Task <bool> TryDequeueAndProcessAsync(CancellationToken cancellationToken) { IReliableQueue <Guid> queue = await this.StateManager.GetOrAddAsync <IReliableQueue <Guid> >(QueueName); IReliableDictionary <Guid, ApplicationDeployment> dictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <Guid, ApplicationDeployment> >(DictionaryName); using (ITransaction tx = this.StateManager.CreateTransaction()) { ConditionalValue <Guid> workItem = await queue.TryDequeueAsync(tx, this.transactionTimeout, cancellationToken); if (!workItem.HasValue) { ServiceEventSource.Current.ServiceMessage(this, "No new application deployment requests."); return(false); } Guid workItemId = workItem.Value; ConditionalValue <ApplicationDeployment> appDeployment = await dictionary.TryGetValueAsync(tx, workItemId, LockMode.Update, this.transactionTimeout, cancellationToken); if (!appDeployment.HasValue) { ServiceEventSource.Current.ServiceMessage( this, "Found queued application deployment request with no associated deployment information. Discarding."); return(true); } ApplicationDeployment processedDeployment = await this.ProcessApplicationDeployment(appDeployment.Value, cancellationToken); if (processedDeployment.Status == ApplicationDeployStatus.Complete || processedDeployment.Status == ApplicationDeployStatus.Failed) { // Remove deployments that completed or failed await dictionary.TryRemoveAsync(tx, workItemId, this.transactionTimeout, cancellationToken); } else { // The deployment hasn't completed or failed, so queue up the next stage of deployment await queue.EnqueueAsync(tx, workItemId, this.transactionTimeout, cancellationToken); // And update the deployment record with the new status await dictionary.SetAsync(tx, workItemId, processedDeployment, this.transactionTimeout, cancellationToken); ServiceEventSource.Current.ServiceMessage( this, "Application deployment request successfully processed. Cluster: {0}. Status: {1}", processedDeployment.Cluster, processedDeployment.Status); } await tx.CommitAsync(); } return(true); }
/// <summary> /// This method executes on the bidder's partition. /// Called by web: priority 0 /// </summary> public async Task <Bid[]> PlaceBidAsync(String bidderEmail, String sellerEmail, String itemName, Decimal bidAmount, CancellationToken ct) { Email _sellerEmail = Email.Parse(sellerEmail); using (var tx = CreateTransaction()) { Email _bidderEmail = Email.Parse(bidderEmail); ItemId itemId = ItemId.Parse(_sellerEmail, itemName); var cr = await m_users.TryGetValueAsync(tx, _bidderEmail); if (!cr.HasValue) { throw new InvalidOperationException($"Bidder '{_bidderEmail}' doesn't exist."); } // Create new User object identical to current with new itemId added to it (if not already in collection [idempotent]) UserInfo userInfo = cr.Value; if (!userInfo.ItemsBidding.Contains(itemId)) { userInfo = userInfo.AddItemBidding(itemId); await m_users.SetAsync(tx, _bidderEmail, userInfo); await tx.CommitAsync(); } // NOTE: If we fail here, the bidder thinks they're bidding on an item but the // item doesn't know about the bidder. If so, the bidder will not see their latest bid. // The bidder could bid again (which is why adding the item is idempotent). } // Tell seller's partition to place a bid var proxy = (IInternalOperations) new ServiceOperations(s_partitionEndpointResolver, AuctionServiceNameUri); return(await proxy.PlaceBid2Async(bidderEmail, sellerEmail, itemName, bidAmount, ct)); }
protected override async Task RunAsync(CancellationToken cancellationToken) { int retryCount = 0; while (!cancellationToken.IsCancellationRequested && retryCount < 5) { try { IReliableDictionary <string, DateTimeOffset> timeDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, DateTimeOffset> >("TimeTracker"); using (ITransaction tx = this.StateManager.CreateTransaction()) { ConditionalValue <DateTimeOffset> result = await timeDictionary.TryGetValueAsync(tx, "StartTime"); if (!result.HasValue) { await timeDictionary.SetAsync(tx, "StartTime", DateTimeOffset.UtcNow); } await tx.CommitAsync(); } return; } catch (TimeoutException te) { // transient error. Retry. retryCount++; ServiceEventSource.Current.ServiceMessage( this, "NationalService encountered an exception trying to record start time: TimeoutException in RunAsync: {0}", te.ToString()); continue; } catch (FabricTransientException fte) { // transient error. Retry. retryCount++; ServiceEventSource.Current.ServiceMessage( this, "NationalService encountered an exception trying to record start time: FabricTransientException in RunAsync: {0}", fte.ToString()); continue; } catch (FabricNotPrimaryException) { // not primary any more, time to quit. return; } catch (Exception ex) { ServiceEventSource.Current.ServiceMessage(this, ex.ToString()); throw; } } }
private async Task ApplyChanges(ITransaction tx, IReliableDictionary <string, CachedItem> cachedItemStore, IReliableDictionary <string, CacheStoreMetadata> cacheStoreMetadata, LinkedDictionaryItemsChanged linkedDictionaryItemsChanged) { foreach (var cacheItem in linkedDictionaryItemsChanged.CachedItemsToUpdate) { await cachedItemStore.SetAsync(tx, cacheItem.Key, cacheItem.Value); } await cacheStoreMetadata.SetAsync(tx, CacheStoreMetadataKey, linkedDictionaryItemsChanged.CacheStoreMetadata); }
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 <IActionResult> NewGame(string roomid, string playerid, string playerdata, string roomtype) { try { if (!RoomManager.IsActive) { return new ContentResult { StatusCode = 503, Content = "Service is still starting up. Please retry." } } ; Player player = JsonConvert.DeserializeObject <Player>(playerdata); //get the general room dictionary IReliableDictionary <string, Room> roomdict = await this.stateManager.GetOrAddAsync <IReliableDictionary <string, Room> >(RoomDictionaryName); //get or add the active room we will put this player in IReliableDictionary <string, ActivePlayer> activeroom = await this.stateManager.GetOrAddAsync <IReliableDictionary <string, ActivePlayer> >(roomid); using (ITransaction tx = this.stateManager.CreateTransaction()) { //Find the room in the room dictionary ConditionalValue <Room> roomOption = await roomdict.TryGetValueAsync(tx, roomid, LockMode.Update); if (!roomOption.HasValue) { //Scenario: Room does not exist yet await roomdict.AddAsync(tx, roomid, new Room(1, roomtype)); } else { //Scenario: Room does exist Room newRoom = roomOption.Value; newRoom.NumPlayers++; await roomdict.SetAsync(tx, roomid, newRoom); } //Add the data to that room await activeroom.SetAsync(tx, playerid, new ActivePlayer(player, DateTime.UtcNow)); await tx.CommitAsync(); } return(new ContentResult { StatusCode = 200, Content = "Successfully Logged In" }); } catch (Exception e) { return(exceptionHandler(e)); } }
private async Task <bool> BackupCallbackAsync(BackupInfo backupInfo, CancellationToken cancellationToken) { ServiceEventSource.Current.ServiceMessage(Context, "Inside backup callback for replica {0}|{1}", this.Context.PartitionId, this.Context.ReplicaId); long totalBackupCount; IReliableDictionary <string, long> backupCountDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, long> >(BackupCountDictionaryName); using (ITransaction tx = this.StateManager.CreateTransaction()) { ConditionalValue <long> value = await backupCountDictionary.TryGetValueAsync(tx, "backupCount"); if (!value.HasValue) { totalBackupCount = 0; } else { totalBackupCount = value.Value; } await backupCountDictionary.SetAsync(tx, "backupCount", ++totalBackupCount); await tx.CommitAsync(); } ServiceEventSource.Current.Message("Backup count dictionary updated, total backup count is {0}", totalBackupCount); try { ServiceEventSource.Current.ServiceMessage(Context, "Archiving backup"); await this.backupManager.ArchiveBackupAsync(backupInfo, cancellationToken); ServiceEventSource.Current.ServiceMessage(Context, "Backup archived"); } catch (Exception e) { ServiceEventSource.Current.ServiceMessage(Context, "Archive of backup failed: Source: {0} Exception: {1}", backupInfo.Directory, e.Message); } try { ServiceEventSource.Current.ServiceMessage(Context, "Deleting backups"); await this.backupManager.DeleteBackupsAsync(cancellationToken); ServiceEventSource.Current.ServiceMessage(Context, "Backups deleted"); } catch (Exception e) { ServiceEventSource.Current.ServiceMessage(Context, "Delete of backup failed: Exception: {1}", e.Message); } return(true); }
public async Task SetDataAsync(long key, byte[] data) { IReliableDictionary <long, byte[]> dictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <long, byte[]> >(this.dictionaryName); using (ITransaction tx = this.StateManager.CreateTransaction()) { await dictionary.SetAsync(tx, key, data); await tx.CommitAsync(); } }
/// <summary> /// This method saves the description (eventString) and timestamp of the recentmost induced fault as /// a ChaosEntry in a Reliable Dictionary /// </summary> /// <param name="eventString"></param> /// <returns>A task to await on</returns> private async Task StoreEventAsync(string eventString) { ServiceEventSource.Current.ServiceMessage(this, "ChaosTest: {0}", eventString); IReliableDictionary <string, long> eventCount = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, long> >(StringResource.EventCountKey); IReliableDictionary <string, DateTime> startTime = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, DateTime> >(StringResource.StartTimeKey); IReliableDictionary <long, ChaosEntry> savedEvents = await this.StateManager.GetOrAddAsync <IReliableDictionary <long, ChaosEntry> >(StringResource.SavedEventsKey); using (ITransaction tx = this.StateManager.CreateTransaction()) { if (!await startTime.ContainsKeyAsync(tx, StringResource.StartTimeKey)) { await startTime.AddAsync(tx, StringResource.StartTimeKey, DateTime.UtcNow); } if (!await eventCount.ContainsKeyAsync(tx, StringResource.EventCountKey)) { await eventCount.AddAsync(tx, StringResource.EventCountKey, 0); } ConditionalValue <long> result = await eventCount.TryGetValueAsync(tx, StringResource.EventCountKey, LockMode.Update); if (result.HasValue) { long currentCount = result.Value; // If we have HistoryLength number of events, we make room for new events by removing oldest ones, // always keeping HistoryLength number of recentmost events on the show on the webpage. if (currentCount > Constants.HistoryLength - 1) { await savedEvents.TryRemoveAsync(tx, currentCount - Constants.HistoryLength + 1); } ChaosEntry chaosEntry = new ChaosEntry { Record = eventString, TimeStamp = DateTime.UtcNow.ToString(CultureInfo.InvariantCulture) }; await savedEvents.AddAsync(tx, ++currentCount, chaosEntry); await eventCount.SetAsync(tx, StringResource.EventCountKey, currentCount); await tx.CommitAsync(); } } }
internal static async Task RemoveSubscription( this IReliableDictionary <string, BrokerServiceState> brokerState, ITransaction tx, string queues, SubscriptionDetails subscriptionDetails) { var subscribers = await brokerState.TryGetValueAsync(tx, queues, LockMode.Update); if (subscribers.HasValue) { var newState = BrokerServiceState.RemoveSubscriber(subscribers.Value, subscriptionDetails); await brokerState.SetAsync(tx, queues, newState); } }
/// <summary> /// Looks for errors in the update tables, and processes one record at a time to create or update corresponding issues. /// </summary> /// <param name="checkPoint">The last record processed datetime.</param> /// <param name="issueRepo">Repository where the gitHub issue has to be created.</param> /// <param name="checkpointEvaluator">Reliable dictionary that holds the time the last record was processed.</param> /// <returns></returns> private async Task CheckForErrorsInUpdateHistoryTablesAsync( DateTimeOffset checkPoint, string issueRepo, IReliableDictionary <string, DateTimeOffset> checkpointEvaluator) { // First get the un-processed entries from the RepositoryBranchHistory table List <UpdateHistoryEntry> unprocessedHistoryEntries = _context.RepositoryBranchUpdateHistory .Where(entry => entry.Success == false && entry.Timestamp > checkPoint.UtcDateTime) .ToList <UpdateHistoryEntry>(); // Add in the SubscriptionUpdate errors: unprocessedHistoryEntries.AddRange( _context.SubscriptionUpdateHistory .Where(entry => entry.Success == false && entry.Timestamp > checkPoint.UtcDateTime)); // Sort union of these sets by timestamp, so the oldest checkpoint is the oldest unprocessed from both update history tables unprocessedHistoryEntries = unprocessedHistoryEntries.OrderBy(entry => entry.Timestamp).ToList(); if (!unprocessedHistoryEntries.Any()) { _logger.LogInformation($"No errors found in the 'RepositoryBranchUpdates' or 'SubscriptionUpdates' tables. The last checkpoint time was : '{checkPoint}'"); return; } foreach (var error in unprocessedHistoryEntries) { try { await IssueDescriptionEvaluator(error, issueRepo); using (ITransaction tx = _stateManager.CreateTransaction()) { await checkpointEvaluator.SetAsync( tx, "checkpointEvaluator", error.Timestamp ); await tx.CommitAsync(); } } catch (TimeoutException exe) { _logger.LogError(exe, $"Unable to update the last processed error timestamp : '{error.Timestamp}"); } catch (Exception ex) { _logger.LogError(ex, $"Unable to create a github issue for error message : '{error.ErrorMessage}' for {GetPrintableDescription(error)}"); } } }
public async Task <IActionResult> Put(string id, [FromBody] JToken values) { try { var userId = values["player"].Value <string>(); var idx = values["idx"].Value <int>(); _logger.Info($"Got move from {userId} for {idx}"); IReliableDictionary <string, Game> gamesDictionary = await _stateManager.GetOrAddAsync <IReliableDictionary <string, Game> >("games"); using (ITransaction tx = _stateManager.CreateTransaction()) { var game = await gamesDictionary.TryGetValueAsync(tx, id); if (!game.HasValue) { return(NotFound()); } if (game.Value.State is TicTacToeState state) { _logger.Info("It was a TicTacToeGame"); var playerMarker = game.Value.UserRoles[userId]; if (state.Board[idx] == null && ((state.IsXTurn && playerMarker == "X") || (!state.IsXTurn && playerMarker == "O"))) { state.Board[idx] = playerMarker; state.IsXTurn = !state.IsXTurn; await gamesDictionary.SetAsync(tx, id, game.Value); await tx.CommitAsync(); } return(Json(state.Board)); } else { _logger.Info("It was not a TicTacToeGame"); return(BadRequest()); } } } catch (Exception e) { _logger.Info(e.ToString()); throw; } }
public async Task DeleteClusterAsync(string name) { IReliableDictionary <string, ClusterOperationStatus> clusters = await this.stateManager.GetOrAddAsync <IReliableDictionary <string, ClusterOperationStatus> >(new Uri("fakeclusterops:/clusters")); using (ITransaction tx = this.stateManager.CreateTransaction()) { await clusters.SetAsync(tx, name, ClusterOperationStatus.Deleting); await tx.CommitAsync(); } }
/// <summary> /// Adds clusters by the given amount without going over the max threshold and without resulting in below the min threshold. /// </summary> /// <param name="targetCount"></param> /// <returns></returns> internal async Task BalanceClustersAsync(int target) { Random random = new Random(); IReliableDictionary <int, Cluster> clusterDictionary = await this.reliableStateManager.GetOrAddAsync <IReliableDictionary <int, Cluster> >(ClusterDictionaryName); using (ITransaction tx = this.reliableStateManager.CreateTransaction()) { var activeClusters = this.GetActiveClusters(clusterDictionary); int activeClusterCount = activeClusters.Count(); if (target < this.Config.MinimumClusterCount) { target = this.Config.MinimumClusterCount; } if (target > this.Config.MaximumClusterCount) { target = this.Config.MaximumClusterCount; } if (activeClusterCount < target) { int limit = Math.Min(target, this.Config.MaximumClusterCount); for (int i = 0; i < limit - activeClusterCount; ++i) { await clusterDictionary.AddAsync(tx, random.Next(), new Cluster()); } await tx.CommitAsync(); } if (activeClusterCount > target) { var removeList = activeClusters .Where(x => x.Value.Users.Count == 0) .Take(Math.Min(activeClusterCount - this.Config.MinimumClusterCount, activeClusterCount - target)); foreach (var item in removeList) { Cluster value = item.Value; value.Status = ClusterStatus.Remove; await clusterDictionary.SetAsync(tx, item.Key, value); } await tx.CommitAsync(); } } }
public async Task <IActionResult> Put(string staff) { IReliableDictionary <string, int> StaffDictionary = await this.stateManager.GetOrAddAsync <IReliableDictionary <string, int> >("counts"); using (ITransaction tx = this.stateManager.CreateTransaction()) { await StaffDictionary.SetAsync(tx, staff, 1); await tx.CommitAsync(); } telemetry.TrackEvent($"Added a Staff for {staff}"); return(new OkResult()); }
/// <inheritdocs/> public async Task SetChunks(Guid replicaId, IEnumerable <Chunk> chunks) { var payload = Utils.Serialize(chunks.ToArray()); await EnsureChunkTables(); using (var tx = ServiceFabricUtils.CreateTransaction()) { await ServiceFabricUtils.DoWithTimeoutRetry( async() => await m_chunktable.SetAsync(tx, replicaId, payload), async() => await tx.CommitAsync()); } }
/// <summary> /// Creates an EventHubReceiver from the given connection sting and partition key. /// The Reliable Dictionaries are used to create a receiver from wherever the service last left off, /// or from the current date/time if it's the first time the service is coming up. /// </summary> /// <param name="connectionString"></param> /// <param name="servicePartitionKey"></param> /// <param name="epochDictionary"></param> /// <param name="offsetDictionary"></param> /// <returns></returns> private async Task<Tuple<EventHubReceiver, MessagingFactory>> ConnectToIoTHubAsync( string connectionString, long servicePartitionKey, IReliableDictionary<string, long> epochDictionary, IReliableDictionary<string, string> offsetDictionary) { // EventHubs doesn't support NetMessaging, so ensure the transport type is AMQP. ServiceBusConnectionStringBuilder connectionStringBuilder = new ServiceBusConnectionStringBuilder(connectionString); connectionStringBuilder.TransportType = TransportType.Amqp; ServiceEventSource.Current.ServiceMessage( this.Context, "RouterService connecting to IoT Hub at {0}", String.Join(",", connectionStringBuilder.Endpoints.Select(x => x.ToString()))); // A new MessagingFactory is created here so that each partition of this service will have its own MessagingFactory. // This gives each partition its own dedicated TCP connection to IoT Hub. MessagingFactory messagingFactory = MessagingFactory.CreateFromConnectionString(connectionStringBuilder.ToString()); EventHubClient eventHubClient = messagingFactory.CreateEventHubClient("messages/events"); EventHubRuntimeInformation eventHubRuntimeInfo = await eventHubClient.GetRuntimeInformationAsync(); EventHubReceiver eventHubReceiver; // Get an IoT Hub partition ID that corresponds to this partition's low key. // This assumes that this service has a partition count 'n' that is equal to the IoT Hub partition count and a partition range of 0..n-1. // For example, given an IoT Hub with 32 partitions, this service should be created with: // partition count = 32 // partition range = 0..31 string eventHubPartitionId = eventHubRuntimeInfo.PartitionIds[servicePartitionKey]; using (ITransaction tx = this.StateManager.CreateTransaction()) { ConditionalValue<string> offsetResult = await offsetDictionary.TryGetValueAsync(tx, "offset", LockMode.Default); ConditionalValue<long> epochResult = await epochDictionary.TryGetValueAsync(tx, "epoch", LockMode.Update); long newEpoch = epochResult.HasValue ? epochResult.Value + 1 : 0; if (offsetResult.HasValue) { // continue where the service left off before the last failover or restart. ServiceEventSource.Current.ServiceMessage( this.Context, "Creating EventHub listener on partition {0} with offset {1}", eventHubPartitionId, offsetResult.Value); eventHubReceiver = await eventHubClient.GetDefaultConsumerGroup().CreateReceiverAsync(eventHubPartitionId, offsetResult.Value, newEpoch); } else { // first time this service is running so there is no offset value yet. // start with the current time. ServiceEventSource.Current.ServiceMessage( this.Context, "Creating EventHub listener on partition {0} with offset {1}", eventHubPartitionId, DateTime.UtcNow); eventHubReceiver = await eventHubClient.GetDefaultConsumerGroup() .CreateReceiverAsync(eventHubPartitionId, DateTime.UtcNow, newEpoch); } // epoch is recorded each time the service fails over or restarts. await epochDictionary.SetAsync(tx, "epoch", newEpoch); await tx.CommitAsync(); } return new Tuple<EventHubReceiver, MessagingFactory>(eventHubReceiver, messagingFactory); }