/// <summary> /// Reports the data backup. /// </summary> /// <param name="casinoDataBackup">The casino data backup.</param> public void ReportDataBackup(CasinoDataBackup casinoDataBackup) { Logger.Debug($"On-Site HMS service sending Casino Data Backup: [{casinoDataBackup}] to HMS Cloud Service"); Channel.ReportDataBackup(casinoDataBackup); }
/// <inheritdoc /> /// <exception cref="T:System.Exception"> /// ServiceConsumerFactory.Create returned null/invalid IHmsCloudService reference. /// Check WCF HMS configuration. /// </exception> public void SendDataBackup(IDictionary <string, IList <byte[]> > backupData) { if (null == backupData || 0 >= backupData.Count) { return; } var casinoCode = Settings.Default.CasinoCode; var dataBackupFilename = string.Empty; var reportGuid = Guid.Empty; using ( var cloudServiceProxy = ServiceConsumerFactory.Create <IHmsCloudService>(() => new HmsCloudServerProxy()) ) { try { if (cloudServiceProxy?.Operations == null) { throw new Exception( "ServiceConsumerFactory.Create returned null/invalid IHmsCloudService reference. Check WCF HMS configuration."); } foreach (var backupFilename in backupData.Keys) { dataBackupFilename = backupFilename; var backupDataFileChunks = backupData[backupFilename]; if (null == backupDataFileChunks || 0 >= backupDataFileChunks.Count) { continue; } // create a new ReportGuid - one for each filename being sent (in either one or // multiple messages/chunks - based on size of backupDataFileChunks IList) reportGuid = Guid.NewGuid(); var reportedAt = DateTime.UtcNow; // The TransactionScope here will provide behavior such that - if/when the call to // DataAggregator.SuccessfulCasinoDataBackup fails for some reason - the transactional // WCF/MSMQ message delivery will be rolled back (i.e., the messages will be discarded // from the client-side MQ) // // Additionally, we bundle all the chunks for each backup data file into a single // transaction. Thus, we will roll back if not all chunks are successfully // processed/sent. var txnOptions = new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead }; using (var txnScope = new TransactionScope(TransactionScopeOption.Required, txnOptions)) { for (var iChunk = 0; iChunk < backupDataFileChunks.Count; ++iChunk) { var chunk = backupDataFileChunks[iChunk]; if (null == chunk || 0 >= chunk.LongLength) { continue; } var casinoDataBackup = new CasinoDataBackup { Filename = backupFilename, Chunk = chunk, ChunkIndex = iChunk, NumChunks = backupDataFileChunks.Count, CasinoCode = casinoCode, ReportGuid = reportGuid, ReportedAt = reportedAt }; cloudServiceProxy.Operations.ReportDataBackup(casinoDataBackup); } DataAggregator.SuccessfulCasinoDataBackup(backupFilename + @".zip", reportGuid); txnScope.Complete(); } } } catch (FaultException fe) { Logger.Warn($"Service operation ReportDataBackup threw a fault: [{fe.Message}]"); if (!string.IsNullOrWhiteSpace(dataBackupFilename)) { DataAggregator.UnsuccessfulCasinoDataBackup(dataBackupFilename + @".zip", reportGuid); } } catch (Exception ex) { Logger.Warn( $"An unexpected error occurred while calling the ReportDataBackup service operation: [{ex.Message}]"); var innerEx = ex.InnerException; while (null != innerEx) { Logger.Warn($"[{innerEx.Message}]"); innerEx = innerEx.InnerException; } Logger.Warn($"Stack Trace: [{Environment.StackTrace}]"); if (!string.IsNullOrWhiteSpace(dataBackupFilename)) { DataAggregator.UnsuccessfulCasinoDataBackup(dataBackupFilename + @".zip", reportGuid); } } } }