private async Task GenerateAndSendHealthReportAsync()
        {
            try
            {
                ConditionalValue <Guid> DoctorIdResult = await this.StateManager.TryGetStateAsync <Guid>("DoctorId");

                string          docIdStr = DoctorIdResult.Value.ToString();
                HeartRateRecord record   = new HeartRateRecord((float)this.random.NextDouble());

                await this.SaveHealthDataAsync(record);

                await FabricHttpClient.MakePostRequest <HeartRateRecord>(
                    this.doctorServiceUri,
                    this.doctorServicePartitionKey,
                    "DoctorEndpoint",
                    "doctor/health/" + docIdStr + "/" + this.Id.GetGuidId(),
                    record,
                    SerializationSelector.PBUF,
                    CancellationToken.None
                    );

                ActorEventSource.Current.Message("Health info sent from band {0} to doctor {1}", this.Id, DoctorIdResult.Value);
            }
            catch (Exception e)
            {
                ActorEventSource.Current.Message(
                    "Band Actor failed to send health data to doctor. Exception: {0}",
                    (e is AggregateException) ? e.InnerException.ToString() : e.ToString());
            }

            return;
        }
        private async Task RegisterPatientReminder()
        {
            ConditionalValue <Guid> DoctorIdResult = await this.StateManager.TryGetStateAsync <Guid>("DoctorId");

            var docIdStr = DoctorIdResult.Value.ToString();

            var prr = new PatientRegistrationRecord(
                await this.StateManager.GetStateAsync <string>("PatientName"),
                this.Id.GetGuidId(),
                await this.StateManager.GetStateAsync <HealthIndex>("HealthIndex")
                );

            await FabricHttpClient.MakePostRequest <PatientRegistrationRecord>(
                this.doctorServiceUri,
                new ServicePartitionKey(HashUtil.getLongHashCode(docIdStr)),
                "DoctorEndpoint",
                "/doctor/new/patient/" + docIdStr,
                prr,
                SerializationSelector.PBUF,
                CancellationToken.None
                );
        }
        public async Task <List <CountyHealth> > GetNationalHealth()
        {
            try
            {
                ServiceUriBuilder serviceUri = new ServiceUriBuilder(this.GetSetting(NationalServiceName));

                var result = await FabricHttpClient.MakeGetRequestAsync <List <CountyHealth> >(
                    serviceUri.ToUri(),
                    new ServicePartitionKey(),
                    "NationalEndpoint",
                    "/national/health",
                    SerializationSelector.PBUF,
                    CancellationToken.None
                    );

                return(result);
            }
            catch (Exception e)
            {
                ServiceEventSource.Current.Message("Exception in Web API Controller getting national health {0}", e);
                throw;
            }
        }
        public async Task <HealthIndex> GetCountyHealth(int countyId)
        {
            try
            {
                ServiceUriBuilder serviceUri = new ServiceUriBuilder(this.GetSetting(CountyServiceName));

                var result = await FabricHttpClient.MakeGetRequestAsync <HealthIndex>(
                    serviceUri.ToUri(),
                    new ServicePartitionKey(countyId),
                    "CountyEndpoint",
                    "/county/health/" + countyId,
                    SerializationSelector.PBUF,
                    CancellationToken.None
                    );

                return(result);
            }
            catch (Exception e)
            {
                ServiceEventSource.Current.Message("Exception in Web API Controller getting county {0} health {1}", countyId, e);
                throw;
            }
        }
        public async Task <IEnumerable <KeyValuePair <Guid, CountyDoctorStats> > > GetDoctors(int countyId)
        {
            try
            {
                ServiceUriBuilder serviceUri = new ServiceUriBuilder(this.GetSetting(CountyServiceName));

                var result = await FabricHttpClient.MakeGetRequestAsync <IEnumerable <KeyValuePair <Guid, CountyDoctorStats> > >(
                    serviceUri.ToUri(),
                    new ServicePartitionKey(countyId),
                    "CountyEndpoint",
                    "/county/doctors/" + countyId,
                    SerializationSelector.PBUF,
                    CancellationToken.None
                    );

                return(result);
            }
            catch (Exception e)
            {
                ServiceEventSource.Current.Message("Exception in Web API Controller getting county {0} doctors: {1}", countyId, e);
                throw;
            }
        }
        public async Task <NationalStatsViewModel> GetNationalStats()
        {
            try
            {
                ServiceUriBuilder serviceUri = new ServiceUriBuilder(this.GetSetting(NationalServiceName));
                var key    = new ServicePartitionKey();
                var result = await FabricHttpClient.MakeGetRequestAsync <NationalStatsViewModel>(
                    serviceUri.ToUri(),
                    key,
                    "NationalEndpoint",
                    "/national/stats",
                    SerializationSelector.PBUF,
                    CancellationToken.None
                    );

                return(result);
            }
            catch (Exception e)
            {
                ServiceEventSource.Current.Message("Exception in Web API Controller getting national stats {0}", e);
                throw;
            }
        }
Exemplo n.º 7
0
        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;
                }
            }
        }
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    await Task.Delay(TimeSpan.FromSeconds(1));

                    ConcurrentDictionary <int, List <KeyValuePair <Guid, string> > > countyDoctorMap = new ConcurrentDictionary <int, List <KeyValuePair <Guid, string> > >();

                    using (ITransaction tx = this.StateManager.CreateTransaction())
                    {
                        var doctorDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <Guid, DoctorCreationRecord> >(DoctorRegistrationDictionaryName);

                        var enumerator = (await doctorDictionary.CreateEnumerableAsync(tx)).GetAsyncEnumerator();

                        while (await enumerator.MoveNextAsync(cancellationToken))
                        {
                            var    doctorListItem = enumerator.Current;
                            Guid   doctorId       = doctorListItem.Key;
                            int    countyId       = doctorListItem.Value.CountyInfo.CountyId;
                            string name           = doctorListItem.Value.DoctorName;

                            //TODO: Evaluate if this will correctly always add, or if it will get overwritten
                            countyDoctorMap.AddOrUpdate(
                                countyId,
                                new List <KeyValuePair <Guid, string> >()
                            {
                                new KeyValuePair <Guid, string>(doctorId, name)
                            },
                                (id, existingList) =>
                            {
                                existingList.Add(new KeyValuePair <Guid, string>(doctorId, name));
                                return(existingList);
                            }
                                );
                        }

                        await tx.CommitAsync();
                    }

                    foreach (KeyValuePair <int, List <KeyValuePair <Guid, string> > > info in countyDoctorMap) //should actually be able to do these in parallel
                    {
                        List <DoctorStatsViewModel> countyDoctorStats = new List <DoctorStatsViewModel>();

                        foreach (var docInfo in info.Value) //these should go in parallel too
                        {
                            int  patientCount      = 0;
                            long healthReportCount = 0;

                            string doctorMetadataDictionaryName = String.Format(DoctorMetadataDictionaryName, docInfo.Key);

                            var doctorMetadataDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, long> >(doctorMetadataDictionaryName);

                            using (ITransaction tx = this.StateManager.CreateTransaction())
                            {
                                var reportCountResult = await doctorMetadataDictionary.TryGetValueAsync(tx, "HealthReportCount");

                                if (reportCountResult.HasValue)
                                {
                                    healthReportCount = reportCountResult.Value;
                                }

                                var patientCountResult = await doctorMetadataDictionary.TryGetValueAsync(tx, "PatientCount");

                                if (patientCountResult.HasValue)
                                {
                                    patientCount = (int)patientCountResult.Value;
                                }

                                await tx.CommitAsync();
                            }

                            HealthIndex avgHealthIndex = await GetAveragePatientHealthInfoAsync(docInfo.Key, cancellationToken);

                            countyDoctorStats.Add(new DoctorStatsViewModel(docInfo.Key, info.Key, patientCount, healthReportCount, avgHealthIndex, docInfo.Value));
                        }

                        await FabricHttpClient.MakePostRequest <List <DoctorStatsViewModel> >(
                            this.CountyServiceUri,
                            new ServicePartitionKey(info.Key),
                            "CountyEndpoint",
                            "county/health/",
                            countyDoctorStats,
                            SerializationSelector.PBUF,
                            cancellationToken
                            );
                    }
                }
                catch (TimeoutException te)
                {
                    // transient error. Retry.
                    ServiceEventSource.Current.ServiceMessage(
                        this.Context,
                        "DoctorService encountered an exception trying to send data to County Service: TimeoutException in RunAsync: {0}",
                        te.ToString());
                }
                catch (FabricNotReadableException fnre)
                {
                    // transient error. Retry.
                    ServiceEventSource.Current.ServiceMessage(
                        this.Context,
                        "DoctorService encountered an exception trying to send data to County Service: FabricNotReadableException in RunAsync: {0}",
                        fnre.ToString());
                }
                catch (FabricTransientException fte)
                {
                    // transient error. Retry.
                    ServiceEventSource.Current.ServiceMessage(
                        this.Context,
                        "DoctorService encountered an exception trying to send data to County Service: FabricTransientException in RunAsync: {0}",
                        fte.ToString());
                }
                catch (HttpRequestException hre)
                {
                    ServiceEventSource.Current.ServiceMessage(
                        this.Context,
                        "DoctorService encountered an exception trying to send data to County Service: HttpRequestException in RunAsync: {0}",
                        hre.ToString());
                }
                catch (FabricNotPrimaryException)
                {
                    // not primary any more, time to quit.
                    return;
                }
                catch (ProtoException pbe)
                {
                    ServiceEventSource.Current.ServiceMessage(
                        this.Context,
                        "DoctorService encountered an exception trying to send data to County Service: ProtoException in RunAsync: {0}",
                        pbe.ToString());
                }
                catch (Exception ex)
                {
                    ServiceEventSource.Current.ServiceMessage(this.Context, "{0}", ex.ToString());
                    throw;
                }
            }
        }
        private async Task CreateDeviceActorAsync(DeviceActorGenerator bag, CancellationToken cancellationToken)
        {
            //TODO: Should be able to replace this with a normal Random
            CryptoRandom random = new CryptoRandom();

            while (!cancellationToken.IsCancellationRequested && this.MaxDevicesToCreatePerService > 0)
            {
                bool created = false;
                while (!created && !cancellationToken.IsCancellationRequested)
                {
                    ActorId bandActorId;
                    Guid    doctorId;
                    int     randomCountyId = -1;
                    string  doctorName     = null;

                    randomCountyId = random.Next(0, bag.doctorsPerCounty.Keys.Count);
                    doctorName     = bag.GetRandomName(random);

                    CountyRecord randomCountyRecord = bag.doctorsPerCounty.Keys.ElementAt(randomCountyId);
                    DeviceInfo   bandActorInfo      = bag.GetRandomHealthStatus(randomCountyRecord, random);

                    try
                    {
                        bandActorId = new ActorId(Guid.NewGuid());
                        doctorId    = bandActorInfo.DoctorId;
                        //doctorId = new ActorId(bandActorInfo.DoctorId);

                        var dcr = new DoctorCreationRecord(doctorName, doctorId, randomCountyRecord);
                        ServicePartitionKey key = new ServicePartitionKey(HashUtil.getLongHashCode(bandActorInfo.DoctorId.ToString()));

                        await FabricHttpClient.MakePostRequest <DoctorCreationRecord>(
                            this.DoctorServiceUri,
                            key,
                            "DoctorEndpoint",
                            "/doctor/new/" + doctorId,
                            dcr,
                            SerializationSelector.PBUF,
                            cancellationToken
                            );

                        IDeviceActor bandActor = ActorProxy.Create <IDeviceActor>(bandActorId, ActorServiceUri);
                        await bandActor.NewAsync(bandActorInfo);

                        ServiceEventSource.Current.Message("Actor created {0} verifying...", bandActorId);

                        created = true;
                    }

                    catch (Exception e)
                    {
                        ServiceEventSource.Current.ServiceMessage(this.Context, "Failed to iniitalize device or doctor. {0}", e.ToString());
                    }
                }

                this.MaxDevicesToCreatePerService--;

                ServiceEventSource.Current.ServiceMessage(this.Context, "Created Actors, {0} remaining", this.MaxDevicesToCreatePerService);

                await Task.Delay(100, cancellationToken);
            }
        }