Ejemplo n.º 1
0
        /// <inheritdoc/>
        public async Task <string> InsertAsync(InfectionReport report, Region region, CancellationToken cancellationToken = default)
        {
            if (report == null)
            {
                throw new ArgumentNullException(nameof(report));
            }
            if (region == null)
            {
                throw new ArgumentNullException(nameof(region));
            }

            region = RegionHelper.AdjustToPrecision(region);

            // Get allowed region boundary
            RegionBoundary boundary = RegionHelper.GetRegionBoundary(region);

            var record = new InfectionReportRecord(report)
            {
                RegionBoundary = new RegionBoundary(boundary),
                PartitionKey   = InfectionReportRecord.GetPartitionKey(region)
            };

            ItemResponse <InfectionReportRecord> response = await this.Container
                                                            .CreateItemAsync <InfectionReportRecord>(
                record,
                new PartitionKey(record.PartitionKey),
                cancellationToken : cancellationToken
                );

            return(response.Resource.Id);
        }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        public async Task <IEnumerable <MessageContainerMetadata> > GetLatestInfoAsync(Region region, long lastTimestamp, CancellationToken cancellationToken = default)
        {
            if (region == null)
            {
                throw new ArgumentNullException(nameof(region));
            }
            else
            {
                // Validate region
                RequestValidationResult validationResult = region.Validate();

                // Validate timestamp
                validationResult.Combine(Validator.ValidateFromRange(
                                             lastTimestamp,
                                             0,
                                             DateTimeOffset.UtcNow.AddDays(1).ToUnixTimeMilliseconds(),
                                             Entities.Validation.Resources.ValidationMessages.InvalidTimestamp));

                lastTimestamp = Math.Max(lastTimestamp, DateTimeOffset.UtcNow.AddDays(-MAX_MESSAGE_AGE_DAYS).ToUnixTimeMilliseconds());

                if (validationResult.Passed)
                {
                    // Get message information from database
                    return(await this._reportRepo.GetLatestAsync(RegionHelper.AdjustToPrecision(region), lastTimestamp, cancellationToken));
                }
                else
                {
                    throw new RequestValidationFailedException(validationResult);
                }
            }
        }
Ejemplo n.º 3
0
        /// <inheritdoc/>
        public async Task <string> PublishAsync(MessageContainer report, Region region, CancellationToken cancellationToken = default)
        {
            // Validate inputs
            if (report == null)
            {
                throw new ArgumentNullException(nameof(report));
            }
            if (region == null)
            {
                throw new ArgumentNullException(nameof(region));
            }

            RequestValidationResult validationResult = report.Validate();

            validationResult.Combine(region.Validate());

            if (validationResult.Passed)
            {
                // Push to upstream data repository
                return(await this._reportRepo.InsertAsync(report, RegionHelper.AdjustToPrecision(region), cancellationToken));
            }
            else
            {
                throw new RequestValidationFailedException(validationResult);
            }
        }
Ejemplo n.º 4
0
        void TestRegion(int lat, int lon, int precision, Region expected)
        {
            var region = RegionHelper.AdjustToPrecision(new Region(lat, lon, precision));

            Assert.AreEqual(expected.LatitudePrefix, region.LatitudePrefix);
            Assert.AreEqual(expected.LongitudePrefix, region.LongitudePrefix);
            Assert.AreEqual(expected.Precision, region.Precision);
        }
Ejemplo n.º 5
0
        /// <inheritdoc/>
        public async Task <string> PublishAsync(IEnumerable <BluetoothSeedMessage> seeds, Region region, long timeAtRequest, CancellationToken cancellationToken = default)
        {
            // Validate inputs
            if (seeds == null || seeds.Count() == 0)
            {
                throw new ArgumentNullException(nameof(seeds));
            }
            if (region == null)
            {
                throw new ArgumentNullException(nameof(region));
            }

            // Validate timestamp
            RequestValidationResult validationResult = Validator.ValidateTimestamp(timeAtRequest);

            // Validate seeds
            foreach (BluetoothSeedMessage seed in seeds)
            {
                validationResult.Combine(seed.Validate());
            }

            if (validationResult.Passed)
            {
                // Build MatchMessage from submitted content
                MessageContainer report = new MessageContainer();

                if (report.BluetoothSeeds is List <BluetoothSeedMessage> asList)
                {
                    asList.AddRange(seeds);
                }
                else
                {
                    foreach (BluetoothSeedMessage seed in seeds)
                    {
                        report.BluetoothSeeds.Add(seed);
                    }
                }

                // Store in data repository
                return(await this._reportRepo.InsertAsync(report, RegionHelper.AdjustToPrecision(region), cancellationToken));
            }
            else
            {
                throw new RequestValidationFailedException(validationResult);
            }
        }
Ejemplo n.º 6
0
        public async Task InsertAsync(MessageContainer report, IEnumerable <Region> regions, CancellationToken cancellationToken = default)
        {
            // Validate inputs
            if (report == null)
            {
                throw new ArgumentNullException(nameof(report));
            }

            // Prepare records to insert (grouped by partition key)
            var recordGroups = regions.Select(
                r => new MessageContainerRecord(report)
            {
                RegionBoundary = new RegionBoundary(
                    RegionHelper.GetRegionBoundary(r)
                    ),
                Region       = RegionHelper.AdjustToPrecision(r),
                PartitionKey = MessageContainerRecord.GetPartitionKey(r)
            }).GroupBy(r => r.PartitionKey);

            // Begin batch operation
            // All MatchMessageRecords will have same PartitionID in this batch
            var batches = recordGroups.Select(g => g.Aggregate(
                                                  this.Container.CreateTransactionalBatch(new PartitionKey(g.Key)),
                                                  (result, item) => result.CreateItem <MessageContainerRecord>(item)));

            // Execute transactions
            // TODO: make a single transaction.
            var responses = await Task.WhenAll(batches.Select(b => b.ExecuteAsync(cancellationToken)));

            var failed = responses.Where(r => !r.IsSuccessStatusCode);

            if (failed.Any())
            {
                throw new Exception(
                          String.Format(
                              "{0} out of {1} insertions failed. Cosmos bulk insert failed with HTTP Status Code {2}.",
                              responses.Count(),
                              failed.Count(),
                              failed.First().StatusCode.ToString()
                              )
                          );
            }
        }