public void GatewaySyncState_SettingWasSaveWithoutValue_ShouldReturnSameValue() { // .: Setup var settingsRepository = new SettingRepository(_dbContext); var gatewaySyncSettingsDao = new GatewaySyncStateSettingsDao(settingsRepository); var settingService = new SettingsService(gatewaySyncSettingsDao); var expectedDate = 1601000400; var testState = new GatewayUploadState() { CreationDateOfLastUploadedKey = expectedDate }; // .: Act settingService.SaveGatewaySyncState(testState); var syncState = settingService.GetGatewayUploadState(); // .: Validate syncState.Should() .NotBeNull() .And.IsSameOrEqualTo(testState); syncState.CreationDateOfLastUploadedKey.Should() .Be(expectedDate); }
public void GatewaySyncState_SettingWasSaveWithoutValue_ShouldReturnEmptyObjectDto() { var settingsRepository = new SettingRepository(_dbContext); var gatewaySyncSettingsDao = new GatewaySyncStateSettingsDao(settingsRepository); var settingService = new SettingsService(gatewaySyncSettingsDao); var testState = new GatewayUploadState(); settingService.SaveGatewaySyncState(testState); var syncState = settingService.GetGatewayUploadState(); syncState.Should() .NotBeNull(); syncState.CreationDateOfLastUploadedKey.Should() .BeNull(); }
public void Save(GatewayUploadState lastSyncState) { var jsonString = JsonSerializer.Serialize(lastSyncState); SetProperty(Keys.UpdateState, jsonString); }
/// <summary> /// Returns the GatewayUploadState object. Default values will be returned if no settings were saved before. /// </summary> /// <returns>GatewaySyncState. Not null.</returns> public GatewayUploadState GetUploadState() { GatewayUploadState syncStatusDto = GetStateOrNull <GatewayUploadState>(Keys.UpdateState); return(syncStatusDto ?? new GatewayUploadState()); }
public void SaveGatewaySyncState(GatewayUploadState lastSyncState) { ModelValidator.ValidateContract(lastSyncState); _syncStateDao.Save(lastSyncState); }
private BatchStatus UploadNextBatch(int batchSize, int keyAgeLimitInDays) { var lastSyncState = _settingsService.GetGatewayUploadState(); // Select only keys from last N days (by date of record creation) var uploadedOnAndAfterTicks = lastSyncState.CreationDateOfLastUploadedKey; var uploadedOnAndAfter = uploadedOnAndAfterTicks.HasValue ? new DateTime(uploadedOnAndAfterTicks.Value, DateTimeKind.Utc) : DateTime.UnixEpoch; int batchSizePlusOne = batchSize + 1; // if it will return n + 1 then there is at last one more records to send // Get key package - collection of the records created (uploaded by mobile app) in the db after {uploadedOn} IList <TemporaryExposureKey> keyPackage = _tempKeyRepository.GetKeysOnlyFromApiOriginCountryUploadedAfterTheDateForGatewayUpload( uploadedOnAndLater: uploadedOnAndAfter, numberOfRecordToSkip: lastSyncState.NumberOfKeysProcessedFromTheLastCreationDate, maxCount: batchSizePlusOne, new KeySource[] { KeySource.SmitteStopApiVersion2 }); // Take all record uploaded after the date. var currBatchStatus = new BatchStatus() { NextBatchExists = keyPackage.Count == batchSizePlusOne }; keyPackage = keyPackage.Take(batchSize).ToList(); currBatchStatus.KeysProcessed = keyPackage.Count; currBatchStatus.ProcessedSuccessfully = true; if (!keyPackage.Any()) { _logger.LogInformation("KeyPackage is empty. Stopping the upload process."); return(currBatchStatus); } _logger.LogInformation($"{keyPackage.Count} records picked."); var oldestKeyFromPackage = keyPackage.Last(); // be aware that it could not be present in the batch. This is the last record (have oldest CreationOn) that has been processed. // Create Batch based on package but filter in on RollingStartNumber. Batch.Size <= Package.Size // We can send data not older than N days ago (age of the key save in key.RollingStartNumber) DateTime createdAfter = DateTime.UtcNow.AddDays(-keyAgeLimitInDays); var createdAfterTimestamp = _epochConverter.ConvertToEpoch(createdAfter); var filteredKeysForBatch = keyPackage .Where(k => k.RollingStartNumber > createdAfterTimestamp) .Where(k => k.DaysSinceOnsetOfSymptoms >= KeyValidator.DaysSinceOnsetOfSymptomsValidRangeMin) .Where(k => k.DaysSinceOnsetOfSymptoms <= KeyValidator.DaysSinceOnsetOfSymptomsValidRangeMax) .ToList(); currBatchStatus.KeysToSend = filteredKeysForBatch.Count; var batch = CreateGatewayBatchFromKeys(filteredKeysForBatch); TemporaryExposureKeyGatewayBatchProtoDto protoBatch = MapBatchDtoToProtoAndSortForSigning(batch); _logger.LogInformation($"{currBatchStatus.KeysToSend} records to send after filtering by age."); if (protoBatch.Keys.Any()) { _logger.LogInformation($"Sending batch..."); currBatchStatus.ProcessedSuccessfully = TrySendKeyBatchToTheGateway(protoBatch, KeysSortOrderUsedToCreateAndVerifyUploadRequestSignature); } else { _logger.LogInformation($"Nothing to sent for this package. All picked keys are older then {keyAgeLimitInDays} days or have incorrect value of DaysSinceOnsetOfSymptoms."); } if (currBatchStatus.ProcessedSuccessfully) { currBatchStatus.KeysSent = protoBatch.Keys.Count; var currSyncState = new GatewayUploadState(); var lastSentKeyTicks = oldestKeyFromPackage.CreatedOn.Ticks; // If the date of the last sent element (recently) has changed in compare the date from the previous batch? // NO - Update the state: Do not change the date, only offset (+=) // YES - Update the state: Change date to the date from last sent element. Update the index to the offset from the first appearance of that date.) if (lastSyncState.CreationDateOfLastUploadedKey == lastSentKeyTicks) { currSyncState.CreationDateOfLastUploadedKey = lastSyncState.CreationDateOfLastUploadedKey; currSyncState.NumberOfKeysProcessedFromTheLastCreationDate = lastSyncState.NumberOfKeysProcessedFromTheLastCreationDate + currBatchStatus.KeysProcessed; } else { currSyncState.CreationDateOfLastUploadedKey = oldestKeyFromPackage.CreatedOn.Ticks; // find offset form fist element with CreationDateOfLastUploadedKey to last sent element var indexOfTheFirstKeyWithTheDate = keyPackage.Select((k, i) => new { Key = k, Index = i }) .First(o => o.Key.CreatedOn.Ticks == lastSentKeyTicks) .Index; currSyncState.NumberOfKeysProcessedFromTheLastCreationDate = currBatchStatus.KeysProcessed - indexOfTheFirstKeyWithTheDate; } // save new sync status _settingsService.SaveGatewaySyncState(currSyncState); } else { _logger.LogError($"Error sending the batch! Stopping upload process."); } return(currBatchStatus); }