public void Update(Saturn5 saturn5) { if (saturn5 is null) { throw new ArgumentNullException(nameof(saturn5)); } if (!this.HasSerialNumberAssociatedEntry(saturn5.SerialNumber)) { throw new ArgumentException("Saturns5DashboardRepository doesn't contain dashboard entry associated with the provided Saturn5.", nameof(saturn5)); } // Thread safety lock lock (this.DashboardDataLock) { // Get live spreadsheets database reference. LiveSpreadsheetsDb db = this._dataRepository.GoogleService.SpreadsheetsDb; IList <string> updatedDashboardEntryRowData = this.GetUpdatedDashboardEntryRowData(saturn5); int serialNumberDashboardRowIndex = this._dashboardRowIndexesBySerialNumbers[saturn5.SerialNumber]; LiveRow saturns5DashboardEntry = this._dashboardSheet[serialNumberDashboardRowIndex]; saturns5DashboardEntry.SetDataFromStringsData(0, updatedDashboardEntryRowData); saturns5DashboardEntry.Upload(db); } }
internal static async Task <Saturns5DashboardRepository> GetAsync(DataRepository dataRepository, string spreadsheetId) { // Saturns5DashboardRepository saturns5DashboardRepository = new Saturns5DashboardRepository(spreadsheetId); // Assign provided data repository. saturns5DashboardRepository._dataRepository = dataRepository; // Get live spreadsheets database reference. LiveSpreadsheetsDb db = saturns5DashboardRepository._dataRepository.GoogleService.SpreadsheetsDb; // Load spreadsheet containing saturns dashboard. await db.LoadSpreadsheetAsync(saturns5DashboardRepository.Saturns5Dashboard_SpreadsheetId); // Get and assign reference to Saturn5_Dashboard spreadsheet and sheet saturns5DashboardRepository._dashboardSpreadsheet = db[saturns5DashboardRepository.Saturns5Dashboard_SpreadsheetId]; saturns5DashboardRepository._dashboardSheet = saturns5DashboardRepository._dashboardSpreadsheet[Saturns5DashboardRepository.Saturns5Dashboard_SheetId]; // Re build serialNumber-rowIndex association index saturns5DashboardRepository.ReBuildDashboardSerialNumberIndex(); saturns5DashboardRepository._dataRepository.UsersDB.UserSpreadsheetLoaded += saturns5DashboardRepository.OnUserSpreadsheetLoaded; saturns5DashboardRepository._dataRepository.UsersDB.UserSpreadsheetAdded += saturns5DashboardRepository.OnUserSpreadsheetAdded; saturns5DashboardRepository._dataRepository.UsersDB.UserSpreadsheetReplaced += saturns5DashboardRepository.OnUserSpreadsheetReplaced; saturns5DashboardRepository._dataRepository.UsersDB.UserSpreadsheetRemoved += saturns5DashboardRepository.OnUserSpreadsheetRemoved; // return(saturns5DashboardRepository); }
// 2) private void AddMissingSaturns5DashboardEntries(LiveSpreadsheetsDb db) { // ADD(append) MISSING ENTRIES IN THE DASHBOARD // Loop through all the serial numbers of the Saturn5 units existing in Saturns5Db, // and append dashboard with new row for each missing one. foreach (KeyValuePair <string, int> rowIndexBySerialNumber in this._dataRepository.Saturns5DB.RowIndexesBySerialNumbers.ToList()) { // Get currently looped through saturns 5 database serial number string dbSerialNumber = rowIndexBySerialNumber.Key; if (this.HasSerialNumberAssociatedEntry(dbSerialNumber)) { continue; } // Get saturn5 associated with the serial number located on currently looped throw row in the Satruns5DB Saturn5 dbSaturn5 = this._dataRepository.Saturn5Repository.Read(dbSerialNumber); // Get new dashboard row entry data using obtained saturn. IList <string> newDashboardEntryRowData = this.GetNewDashboardEntryRowData(dbSaturn5); // Append current dashboard missing saturn 5 dashboard entry representing obtained saturn into this._dashboardSheet this._dashboardSheet.AppendRows(db, Saturns5DashboardRepository.Saturns5Dashboard_EntryRowsCount, new IList <string>[Saturns5DashboardRepository.Saturns5Dashboard_EntryRowsCount] { newDashboardEntryRowData }); // Rebuild dashboard serial numbers - entry row index quick access relativity index this.ReBuildDashboardSerialNumberIndex(); } }
// Creates new Saturns5DashboardEntry based on the saturn 5 unit existing withing Saturns5DB, and specified with provided serial number. public void Create(Saturn5 saturn5) { if (saturn5 is null) { throw new ArgumentNullException(nameof(saturn5)); } if (this.HasSerialNumberAssociatedEntry(saturn5.SerialNumber)) { throw new ArgumentException("Saturns5DashboardRepository already contains dashboard entry associated with the provided Saturn5 serial number.", nameof(saturn5)); } // Thread safety lock lock (this.DashboardDataLock) { // Get live spreadsheets database reference. LiveSpreadsheetsDb db = this._dataRepository.GoogleService.SpreadsheetsDb; // Get new dashboard entry row data IList <string> dashboardEntryRowData = this.GetNewDashboardEntryRowData(saturn5); // Append dashboard sheet with the row representing dashboard entry associated with provided Saturn5 this._dashboardSheet.AppendRows(db, Saturns5DashboardRepository.Saturns5Dashboard_NewEntryRowsCount, new IList <string>[Saturns5DashboardRepository.Saturns5Dashboard_NewEntryRowsCount] { dashboardEntryRowData }); // Creates serial number-rowIndex association in the repository for the newly created this._dashboardRowIndexesBySerialNumbers.Add(saturn5.SerialNumber, this._dbRowIndexesBySerialNumbers[saturn5.SerialNumber] + 1); } }
public void ReObtainData() { // Thread safety lock lock (this.DashboardDataLock) { // Get live spreadsheets database reference. LiveSpreadsheetsDb db = this._dataRepository.GoogleService.SpreadsheetsDb; // Re-obtain users sheet data from google servers this._dashboardSheet.ReObtainData(db); } }
internal static async Task <Saturns5MovementRepository> GetAsync(DataRepository dataRepository, string spreadsheetId) { // Saturns5MovementRepository saturns5MovementRepository = new Saturns5MovementRepository(spreadsheetId); // Assign provided data repository. saturns5MovementRepository._dataRepository = dataRepository; // Get live spreadsheets database reference. LiveSpreadsheetsDb db = saturns5MovementRepository._dataRepository.GoogleService.SpreadsheetsDb; // Load spreadsheet containing saturns dashboard. await db.LoadSpreadsheetAsync(saturns5MovementRepository.Saturns5Movement_SpreadsheetId); // Get and assign reference to Movement spreadsheet and sheet saturns5MovementRepository._dashboardSpreadsheet = db[saturns5MovementRepository.Saturns5Movement_SpreadsheetId]; saturns5MovementRepository._movementSheet = saturns5MovementRepository._dashboardSpreadsheet[Saturns5MovementRepository.Saturns5Movement_SheetId]; return(saturns5MovementRepository); }
// Assures grid data... // (exactly the same number of entries indexed to the same primary key serial number at the same row index // - adjusted for the difference caused by the fact that the dashboards top row contains the header and as such associated entries // are located on the row index greater by 1 then the index of the associated Saturn5DB entry) of this._dashboardSheet // and LiveSheet representing Saturns5DB sheet) // ...consistency between current Saturns5DashboardRepository and Saturn5Repository by removing // Saturns5DashbordEntries associated with unrecognized serial numbers, and correcting incorrect dashboard short ids, // As well as adding missing entries. (Content of other cells then dashboard entries serial numbers still has to be updated) internal async Task AssureGridDataConsistencyAsync() { await Task.Run(() => { // Get live spreadsheets database reference. LiveSpreadsheetsDb db = this._dataRepository.GoogleService.SpreadsheetsDb; // 1) this.RemoveSurplusSaturns5DashboardEntries(db); // 2) this.AddMissingSaturns5DashboardEntries(db); // 3) this.AssureRowIndexLocationSaturns5DashboardEntries(db); // 4) Final rebuild of dashboard serial numbers - entry row quick access relativity dictionary index. this.ReBuildDashboardSerialNumberIndex(); }); }
// 1) private void RemoveSurplusSaturns5DashboardEntries(LiveSpreadsheetsDb db) { // REMOVE DASHBOARD ENTRIES NOT EXISITING IN THE SATURN5 DATABASE // Get all rows from this._dashboardSheet, excluding header row. IList <LiveRow> dashboardRowEntries = this._dashboardSheet.SheetRows.ToList(); dashboardRowEntries.RemoveAt(Saturns5DashboardRepository.Saturns5Dashboard_HeaderRowIndex); foreach (LiveRow dashboardRow in dashboardRowEntries) { string dashboardRowSerialNumber = dashboardRow[Saturns5DashboardRepository.Saturns5Dashboard_SerialNumber].GetDataAsString(); string dashboardRowShortId = dashboardRow[Saturns5DashboardRepository.Saturns5Dashboard_ShortId].GetDataAsString(); if (!this._dataRepository.Saturn5Repository.HasSaturn5SerialNumber(dashboardRowSerialNumber)) { this._dashboardSheet.RemoveRows(db, dashboardRow.RowIndex, 1); // Rebuild dashboard serial numbers - entry row index quick access relativity index this.ReBuildDashboardSerialNumberIndex(); } } }
// Delete public void Delete(string serialNumber) { if (serialNumber is null) { throw new ArgumentNullException(nameof(serialNumber)); } if (!this.HasSerialNumberAssociatedEntry(serialNumber)) { throw new ArgumentException("Saturns5DashboardRepository doesn't contain dashboard entry associated with the provided serial number.", nameof(serialNumber)); } // Thread safety lock lock (this.DashboardDataLock) { // Get live spreadsheets database reference. LiveSpreadsheetsDb db = this._dataRepository.GoogleService.SpreadsheetsDb; int serialNumberDashboardRowIndex = this._dashboardRowIndexesBySerialNumbers[serialNumber]; this._dashboardSheet.RemoveRows(db, serialNumberDashboardRowIndex, Saturns5DashboardRepository.Saturns5Dashboard_NewEntryRowsCount); // Rebuild serial number-dashboard row index association dictionary. this.ReBuildDashboardSerialNumberIndex(); } }
// Dispose entire LiveGoogle service public void Dispose() { // Stop available quota execution. SessionRequestsLimiter.Instance.StopQuotaCount(); // Dispose sessions repository this._sessionsRepository?.Dispose(); this._sessionsRepository = null; // Dispose google apis sheets service this._apisSheetsService?.Dispose(); this._apisSheetsService = null; // Dispose google apis drive service this._apisDriveService?.Dispose(); this._apisDriveService = null; // Dispose spreadsheetsDb together with all its content. this._spreadsheetsDb?.Dispose(); this._spreadsheetsDb = null; // Cancel and get rid of user credentials this._googleApisUser = null; }
// Log out off the google apis public async Task DisconnectAsync() { // Set connection state flag to null. if (this.IsConnected != false) { this.IsConnected = null; } // Stop available quota execution. SessionRequestsLimiter.Instance.StopQuotaCount(); // Await ending session await this._sessionsRepository.EndSessionAsync(); // Dispose _sessions repository ... this._sessionsRepository?.Dispose(); this._sessionsRepository = null; // Dispose google apis service... this._apisSheetsService?.Dispose(); this._apisSheetsService = null; // .. and google drive service. this._apisDriveService.Dispose(); this._apisDriveService = null; // Dispose live spreadsheets data... this._spreadsheetsDb.Dispose(); this._spreadsheetsDb = null; // Dispose google apis user credentials this._googleApisUser = null; // Set connection state flag to false. this.IsConnected = false; }
// Create public void AddSendToITFaultedAndDamagedLog(string serialNumber, string consignmentNumber, string incidentNumber, string sentBy, string damagedBy, string faultReportedBy, string damageDescription, string movementNote) { // Validate parameters if (serialNumber is null) { throw new ArgumentNullException(nameof(serialNumber)); } else if (sentBy is null) { throw new ArgumentNullException(nameof(sentBy)); } else if (damagedBy is null) { throw new ArgumentNullException(nameof(damagedBy)); } else if (faultReportedBy is null) { throw new ArgumentNullException(nameof(faultReportedBy)); } else if (damageDescription is null) { throw new ArgumentNullException(nameof(damageDescription)); } else if (!this.Saturn5Repository.HasSaturn5SerialNumber(serialNumber)) { throw new ArgumentException($"Provided {serialNumber} is not recognized.", nameof(serialNumber)); } else if (!this.UserRepository.HasUsername(sentBy)) { throw new ArgumentException($"Provided {sentBy} is not recognized.", nameof(sentBy)); } // Get necessary data // Get database reference. LiveSpreadsheetsDb db = this._dataRepository.GoogleService.SpreadsheetsDb; // Get timestamp string timestamp = DateTime.Now.ToTimestamp(); // Obtain saturn 5 spreadsheet id... string saturn5SpreadsheetId = this.Saturn5Repository.GetSaturn5LogSpreadsheetId(serialNumber); // ... and URL based on it. string saturn5SpreadsheetURL = this.GetUrlFromSpreadsheetId(saturn5SpreadsheetId); // Prepare data to commit // Create new row blueprint... IList <IList <string> > saturn5MovementLogRowData = new IList <string>[Saturns5MovementRepository.Saturns5Movement_EntryRowsCount] { new string[Saturns5MovementRepository.Saturns5Movement_ColumnsCount] }; // .. and fill it with data.. (0 as first (and only) row of the data in the one-row-grid provided to 'AppendRows' method). // 'Timestamp:' - when send to IT has been logged. saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_Timestamp_ColumnsIndex] = timestamp; // 'Serial Number:' of the saturn 5 unit send to IT. saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_SerialNumber_ColumnsIndex] = serialNumber; // 'Consignment Number:' used to send unit to IT. saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_ConsignmentNumber_ColumnsIndex] = consignmentNumber; // 'Incident Number:' associated with saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_IncidentNumber_ColumnsIndex] = incidentNumber; // 'Saturn 5 Spreadsheet URL:' last known saturn5 unit spreadsheetURL saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_Saturn5SpreadsheetURL_ColumnsIndex] = saturn5SpreadsheetURL; // 'Received / Sent:' - Sent saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_ReceivedOrSent_ColumnsIndex] = Saturn5MovementType.Sent.ToString(); // 'Received by/ Sent by:' Send by - Username. saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_ReceivedOrSentByUsername_ColumnsIndex] = sentBy; // 'Physical damage:' - boolean flag indicating whether unit is damage or not. saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_PhysicalDamage_ColumnsIndex] = true.ToString(); // 'Damaged by username:'******'Non-physical issue::' - boolean flag indicating whether unit is faulty or not. saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_NonPhysicalIssue_ColumnsIndex] = true.ToString(); // 'Non-physical issue reported by:' - Username of the user responsible for reporting unit fault. saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_NonPhysicalIssueReportedByUsername_ColumnsIndex] = faultReportedBy; // 'Damage/Issue description:' - damage description saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_DamageOrIssueDescription_ColumnsIndex] = damageDescription; // 'Received by note/ Sent by note:' - Movement note saturn5MovementLogRowData[0][Saturns5MovementRepository.Saturns5Movement_ReceivedOrSentByNote_ColumnsIndex] = movementNote; // Commit data. this._movementSheet.AppendRows(db, Saturns5MovementRepository.Saturns5Movement_EntryRowsCount, saturn5MovementLogRowData); }
// 3) private void AssureRowIndexLocationSaturns5DashboardEntries(LiveSpreadsheetsDb db) { // ASSURE ROW INDEXES INTEGRITY BETWEEN ALL ENTRIES EXISTING ENTRIES IN THE Saturns5DashboardsRepository and Saturn5Repository bool modified = false; do { modified = false; foreach (KeyValuePair <string, int> rowIndexBySerialNumber in this._dataRepository.Saturns5DB.RowIndexesBySerialNumbers.ToList()) { // Get currently looped through saturns 5 database serial number string dbSerialNumber = rowIndexBySerialNumber.Key; // Get currently saturns 5 database row index. int dbRowIndex = rowIndexBySerialNumber.Value; // Get row dashboard row currently located on the dbRow saturn 5 serial number associated row LiveRow dashboardRow = this._dashboardSheet.SheetRows.ElementAtOrDefault(dbRowIndex + 1); // Get saturn 5 serial number currently stored in the dashboard row entry located at the same rowIndex // as the currently looped through saturn 5 DB row. string dashboardRowSerialNumber = dashboardRow[Saturns5DashboardRepository.Saturns5Dashboard_SerialNumber].GetDataAsString(); // if dbRow index is in the scope of this._dashboardSheet // and dashbordRow contains serial number matching serial number // located on the row with matching index in the saturn 5 database if (dbSerialNumber == dashboardRowSerialNumber) { // (TO BRAKE OUT OF DO WHILE LOOP - each of looped through entries in // the foreach loop should terminate here). continue; } #region WARRNING - int dashboardRowIndex variable // WARRNING - DO NOT REPLACE with indexer from this._dashboardRowIndexesBySerialNumbers[] // at this point this quick-access serialNumber-dashboardRowIndex dictionary is in INVALID state... // (as content of this._dashboardSheet has been potentially already partially modified, // but quick-access serialNumber -dashboardRowIndex dictionary index hasn't been modified accordingly yet // - and it cannot be modified before all of the content of this._dashboardSheet will be corrected), // ...and dashboardRowIndex has to be found using LINQ instead, to obtain valid data. #endregion // Get row index of the entry in this_dashboardSheet having equal serial number then the one in // the currently looped through Saturns5DB row. int dashboardRowIndex = this._dashboardSheet.SheetRows.First((dashboardSheetRow) => { return(dashboardSheetRow[Saturns5DashboardRepository.Saturns5Dashboard_SerialNumber].GetDataAsString() == dbSerialNumber); } ).RowIndex; // Else if serial number located on the currently looped through saturns5 database row, // can be found one of this._dashbordSheet rows, but it is located ABOVE its intended location. if (dashboardRowIndex != dbRowIndex) { // Get row data from its current position IList <string> newDashboardEntryRowData = this._dashboardSheet[dashboardRowIndex].GetDataAsStrings(); // Remove it from its current position this._dashboardSheet.RemoveRows(db, dashboardRowIndex, Saturns5DashboardRepository.Saturns5Dashboard_EntryRowsCount); // Insert it into its designated position this._dashboardSheet.InsertRows(db, dbRowIndex + 1, Saturns5DashboardRepository.Saturns5Dashboard_EntryRowsCount, new IList <string>[Saturns5DashboardRepository.Saturns5Dashboard_EntryRowsCount] { newDashboardEntryRowData }); // Set flag to indicate that content of this._dashboardSheet has been modified modified = true; } else { throw new InvalidOperationException($"THIS SHOULD NOT HAPPENED - CLEARLY INVALID LOGIC IMPLEMENTATION - {nameof(Saturns5DashboardRepository)}"); } } } while (modified); }
// Update public void UpdateUserDetails(User user) { // Thread safety lock lock (this.DashboardDataLock) { // Get live spreadsheets database reference. LiveSpreadsheetsDb db = this._dataRepository.GoogleService.SpreadsheetsDb; // Loop through all the rows in the dashboard // Loop through each of the rows (apart from the header row) in the LiveSheet containing saturn 5 database. for (int i = 1; i < this._dashboardSheet.RowCount; i++) { // Obtain dashboard row located on the currently looped through index... LiveRow dashboardRow = this._dashboardSheet[i]; // ... get the cell containing last seen Username for the specific saturn unit located on the dashboard row... LiveCell usernameCell = dashboardRow[Saturns5DashboardRepository.Saturns5Dashboard_LastSeenUserUsername]; // ... get the username data from that cell... string dashboardRowUsername = usernameCell.GetDataAsString(); // ... and compare provided user Username with dashboard row saturn 5 last seen username, // if they are found being equal, update data in other user related cells. if (user.Username == dashboardRowUsername) { // Boolean flag indicating necessity for updating the changes. bool changesRequired = false; LiveCell firstNameCell = dashboardRow[Saturns5DashboardRepository.Saturns5Dashboard_LastSeenUserFirstName]; LiveCell surnameCell = dashboardRow[Saturns5DashboardRepository.Saturns5Dashboard_LastSeenUserSurname]; LiveCell userSpreadsheetURLCell = dashboardRow[Saturns5DashboardRepository.Saturns5Dashboard_LastSeenUserSpreadsheetURL]; LiveCell saturn5StatusCell = dashboardRow[Saturns5DashboardRepository.Saturns5Dashboard_Status]; string currentFirstName = firstNameCell.GetDataAsString(); string currentSurname = surnameCell.GetDataAsString(); string currentSpreadsheetURL = userSpreadsheetURLCell.GetDataAsString(); // Obtain status from the dashboard cell associated with the saturn 5 // with (according dashboard) the same last user as the one provided for update. Saturn5Status currentStatus = Saturn5StatusService.GetStatusFromDashboardString(saturn5StatusCell.GetDataAsString()); if (currentStatus.IsWithUser()) { // Get saturn5 status according the type of the user the saturn5 is getting allocated to. Saturn5Status status = user.Type.GetWithUserSaturn5Status(); if (currentStatus != status) { changesRequired = true; saturn5StatusCell.SetData(Saturn5StatusService.GetDashboardString(status)); } } if (currentFirstName != user.FirstName) { changesRequired = true; firstNameCell.SetData(user.FirstName); } if (currentSurname != user.Surname) { changesRequired = true; surnameCell.SetData(user.Surname); } string userSpreadsheetId = this._dataRepository.UserRepository.GetUserLogSpreadsheetId(dashboardRowUsername); string newSpreadsheetURL = this.GetUrlFromSpreadsheetId(userSpreadsheetId); if (currentSpreadsheetURL != newSpreadsheetURL) { changesRequired = true; userSpreadsheetURLCell.SetData(newSpreadsheetURL); } if (changesRequired) { dashboardRow.Upload(db); } } } } }
// OwnInstanceSessionIsActiveOrActivatingException - If live google is already connected or in a process of getting activated by the current instance of an application. // Thrown from StartNewSessionAsync only: // OperationCanceledException - On operation canceled... // OtherInstanceSessionAlreadyActiveException - When unable to start new session activation because other application instance currently owns active session, // or failed during active session and didn't clean up 'Last' stamp after itself as recently that this stamp is not considered as unresponsive yet. // OtherInstanceSessionAlreadyStartingException - When unable to start new session activation because other application instance is currently in a process of starting new session, // or failed during activation process and didn't clean up one of the 'ConnectedIn' stamps after itself as recently that this stamps are not considered as unresponsive yet. // SessionActivationInterruptedByOwnInstanceException - When ongoing new session activation has been interrupted and failed because own application instance attempted to start // another new session when process of activating new session if already ongoing. Should occur only in case of cross thread calls, which the method should be protected from with _sessionsLock. // SessionActivationInterruptedByOtherInstanceException - When ongoing new session activation has been interrupted and failed because other application instance, // either began the new session activation process, or activating session by updating value of 'Connected' stamp public async Task <Task> ConnectAsync(CancellationTokenSource cancellationTokenSource, bool forceOtherInstanceActiveSessionTakeover) { if (this.IsConnected != false) { throw new OwnInstanceSessionIsActiveOrActivatingException(); } // Set connection state flag to null. this.IsConnected = null; // Assign allocation token source. this._sessionTokenSource = cancellationTokenSource; // Declare maintainConnectionTask variable. Task maintainConnectionTask; #region Try try { await Task.Run(() => { // Get and assign google apis user credentials. this._googleApisUser = this.GetGoogleApisUserCredential(); // Get and assign google apis sheets service. this._apisSheetsService = this.GetApisSheetsService(); // Get and assign google apis drive service. this._apisDriveService = this.GetApisDriveService(); }); // Initialize session requests limiter. await SessionRequestsLimiter.Instance.StartQuotaCount(this._apisSheetsService, this._sessionsSpreadsheetId, this._sessionTokenSource.Token); await Task.Run(() => { // Get spreadsheets database. this._spreadsheetsDb = this.GetSpreadsheetsDb(); // Get sessions repository this._sessionsRepository = new SessionsRepository(this, this._sessionsSpreadsheetId); }); // Await new active session to start maintainConnectionTask = await this._sessionsRepository.StartNewSessionAsync(this._sessionTokenSource, forceOtherInstanceActiveSessionTakeover); } #endregion #region Catch catch { // Stop available quota execution. SessionRequestsLimiter.Instance.StopQuotaCount(); // Dispose sessions repository this._sessionsRepository?.Dispose(); this._sessionsRepository = null; // Dispose spreadsheets database. this._spreadsheetsDb?.Dispose(); this._spreadsheetsDb = null; // Dispose and assign google apis drive service. this._apisDriveService?.Dispose(); this._apisDriveService = null; // Dispose and assign google apis sheets service. this._apisSheetsService?.Dispose(); this._apisSheetsService = null; // Get and assign google apis user credentials. this._googleApisUser = null; // Set connection state flag to false. this.IsConnected = false; throw; } #endregion // Set connection state flag to true. this.IsConnected = true; // return connection maintenance task return(maintainConnectionTask); }