public async Task <IHttpActionResult> Post([FromUri] int countyId, [FromBody] CountyStatsViewModel status) { IReliableDictionary <int, NationalCountyStats> dictionary = await this.stateManager.GetOrAddAsync <IReliableDictionary <int, NationalCountyStats> >(HealthStatusDictionary); using (ITransaction tx = this.stateManager.CreateTransaction()) { await dictionary.SetAsync( tx, countyId, new NationalCountyStats( status.DoctorCount, status.PatientCount, status.HealthReportCount, status.AverageHealthIndex)); await tx.CommitAsync(); } ServiceEventSource.Current.Message("National Service recieved and saved report {0}|{1}", countyId, status); return(this.Ok()); }
protected override async Task RunAsync(CancellationToken cancellationToken) { ConfigurationPackage configPackage = this.Context.CodePackageActivationContext.GetConfigurationPackageObject("Config"); this.UpdateConfigSettings(configPackage.Settings); this.Context.CodePackageActivationContext.ConfigurationPackageModifiedEvent += this.CodePackageActivationContext_ConfigurationPackageModifiedEvent; this.indexCalculator = new HealthIndexCalculator(this.Context); ServicePrimer primer = new ServicePrimer(); await primer.WaitForStatefulService(this.nationalServiceInstanceUri); IReliableDictionary <int, string> countyNamesDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <int, string> >(CountyNameDictionaryName); ServiceEventSource.Current.ServiceMessage(this, "CountyService starting data processing."); while (!cancellationToken.IsCancellationRequested) { try { //every ten seconds, grab the counties and send them to national await Task.Delay(this.interval, cancellationToken); ServicePartitionClient <HttpCommunicationClient> servicePartitionClient = new ServicePartitionClient <HttpCommunicationClient>( this.clientFactory, this.nationalServiceInstanceUri); IList <KeyValuePair <int, string> > countyNames = new List <KeyValuePair <int, string> >(); using (ITransaction tx = this.StateManager.CreateTransaction()) { IAsyncEnumerator <KeyValuePair <int, string> > enumerator = (await countyNamesDictionary.CreateEnumerableAsync(tx)).GetAsyncEnumerator(); while (await enumerator.MoveNextAsync(cancellationToken)) { countyNames.Add(enumerator.Current); } } foreach (KeyValuePair <int, string> county in countyNames) { IReliableDictionary <Guid, CountyDoctorStats> countyHealth = await this.StateManager.GetOrAddAsync <IReliableDictionary <Guid, CountyDoctorStats> >( string.Format(CountyHealthDictionaryName, county.Key)); int totalDoctorCount = 0; int totalPatientCount = 0; int totalHealthReportCount = 0; int avgHealth = 0; using (ITransaction tx = this.StateManager.CreateTransaction()) { IAsyncEnumerable <KeyValuePair <Guid, CountyDoctorStats> > healthRecords = await countyHealth.CreateEnumerableAsync(tx); IAsyncEnumerator <KeyValuePair <Guid, CountyDoctorStats> > enumerator = healthRecords.GetAsyncEnumerator(); IList <KeyValuePair <Guid, CountyDoctorStats> > records = new List <KeyValuePair <Guid, CountyDoctorStats> >(); while (await enumerator.MoveNextAsync(cancellationToken)) { records.Add(enumerator.Current); } avgHealth = this.indexCalculator.ComputeAverageIndex(records.Select(x => x.Value.AverageHealthIndex)); foreach (KeyValuePair <Guid, CountyDoctorStats> item in records) { totalDoctorCount++; totalPatientCount += item.Value.PatientCount; totalHealthReportCount += item.Value.HealthReportCount; } } CountyStatsViewModel payload = new CountyStatsViewModel(totalDoctorCount, totalPatientCount, totalHealthReportCount, avgHealth); await servicePartitionClient.InvokeWithRetryAsync( client => { Uri serviceAddress = new Uri(client.BaseAddress, string.Format("national/health/{0}", county.Key)); HttpWebRequest request = WebRequest.CreateHttp(serviceAddress); request.Method = "POST"; request.ContentType = "application/json"; request.Timeout = (int)client.OperationTimeout.TotalMilliseconds; request.ReadWriteTimeout = (int)client.ReadWriteTimeout.TotalMilliseconds; using (Stream requestStream = request.GetRequestStream()) { using (BufferedStream buffer = new BufferedStream(requestStream)) { using (StreamWriter writer = new StreamWriter(buffer)) { JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(writer, payload); buffer.Flush(); } using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { ServiceEventSource.Current.ServiceMessage(this, "County Data Sent {0}", serviceAddress); return(Task.FromResult(true)); } } } }, cancellationToken); } } catch (TaskCanceledException) { throw; } catch (Exception exception) { ServiceEventSource.Current.ServiceMessage( this, "CountyService encountered an exception trying to send data to National Service: {0}", exception.ToString()); continue; } } }
protected override async Task RunAsync(CancellationToken cancellationToken) { ServiceEventSource.Current.ServiceMessage(this.Context, "CountyService starting data processing."); while (!cancellationToken.IsCancellationRequested) { try { //every interval seconds, grab the counties and send them to national await Task.Delay(TimeSpan.FromSeconds(int.Parse(this.GetSetting("UpdateFrequency"))), cancellationToken); IReliableDictionary <int, string> countyNamesDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <int, string> >(CountyNameDictionaryName); IList <KeyValuePair <int, string> > countyNames = new List <KeyValuePair <int, string> >(); using (ITransaction tx = this.StateManager.CreateTransaction()) { var enumerator = (await countyNamesDictionary.CreateEnumerableAsync(tx)).GetAsyncEnumerator(); while (await enumerator.MoveNextAsync(cancellationToken)) { countyNames.Add(enumerator.Current); } await tx.CommitAsync(); } foreach (KeyValuePair <int, string> county in countyNames) { IReliableDictionary <Guid, CountyDoctorStats> countyHealth = await this.StateManager.GetOrAddAsync <IReliableDictionary <Guid, CountyDoctorStats> >( string.Format(CountyHealthDictionaryName, county.Key)); int totalDoctorCount = 0; int totalPatientCount = 0; long totalHealthReportCount = 0; //double priorAvg = 0; //double expandedAverage = 0; //double newTotal = 0; IList <KeyValuePair <Guid, CountyDoctorStats> > records = new List <KeyValuePair <Guid, CountyDoctorStats> >(); using (ITransaction tx = this.StateManager.CreateTransaction()) { var enumerator = (await countyHealth.CreateEnumerableAsync(tx, EnumerationMode.Unordered)).GetAsyncEnumerator(); while (await enumerator.MoveNextAsync(cancellationToken)) { records.Add(enumerator.Current); } await tx.CommitAsync(); } foreach (KeyValuePair <Guid, CountyDoctorStats> item in records) { //expandedAverage = priorAvg * totalDoctorCount; //newTotal = expandedAverage + item.Value.AverageHealthIndex.GetValue(); totalDoctorCount++; totalPatientCount += item.Value.PatientCount; totalHealthReportCount += item.Value.HealthReportCount; //priorAvg = newTotal / totalHealthReportCount; } HealthIndex avgHealth; if (records.Count > 0) { avgHealth = this.indexCalculator.ComputeAverageIndex(records.Select(x => x.Value.AverageHealthIndex)); } else { avgHealth = this.indexCalculator.ComputeIndex(-1); } CountyStatsViewModel payload = new CountyStatsViewModel(totalDoctorCount, totalPatientCount, totalHealthReportCount, avgHealth); ServiceUriBuilder serviceUri = new ServiceUriBuilder(this.GetSetting("NationalServiceInstanceName")); await FabricHttpClient.MakePostRequest <CountyStatsViewModel>( serviceUri.ToUri(), new ServicePartitionKey(), "NationalEndpoint", "/national/health/" + county.Key, payload, SerializationSelector.PBUF, cancellationToken ); } } catch (TimeoutException te) { // transient error. Retry. ServiceEventSource.Current.ServiceMessage( this.Context, "CountyService encountered an exception trying to send data to National Service: TimeoutException in RunAsync: {0}", te.ToString()); } catch (FabricNotReadableException fnre) { ServiceEventSource.Current.ServiceMessage( this.Context, "CountyService encountered an exception trying to send data to National Service: TimeoutException in RunAsync: {0}", fnre.ToString());// transient error. Retry. } catch (FabricTransientException fte) { // transient error. Retry. ServiceEventSource.Current.ServiceMessage( this.Context, "CountyService encountered an exception trying to send data to National Service: FabricTransientException in RunAsync: {0}", fte.ToString()); } catch (FabricNotPrimaryException) { // not primary any more, time to quit. return; } catch (HttpRequestException hre) { ServiceEventSource.Current.ServiceMessage( this.Context, "CountyService encountered an exception trying to send data to National Service: HttpRequestException in RunAsync: {0}", hre.ToString()); } catch (ProtoException pbe) { ServiceEventSource.Current.ServiceMessage( this.Context, "CountyService encountered an exception trying to send data to National Service: ProtoException in RunAsync: {0}", pbe.ToString()); } catch (Exception ex) { ServiceEventSource.Current.ServiceMessage(this.Context, "{0}", ex.ToString()); throw; } } }