private void PersistActivityProgress(ActivityProgress activityProgress, OperationName operationName, OperationState?operationState = null, int?operationContactCount = null, string operationDuration = null) { activityProgress.Operations[operationName.ToString()].Duration = operationDuration ?? activityProgress.Operations[operationName.ToString()].Duration; activityProgress.Operations[operationName.ToString()].ContactCount = operationContactCount ?? activityProgress.Operations[operationName.ToString()].ContactCount; activityProgress.Operations[operationName.ToString()].OperationState = operationState ?? activityProgress.Operations[operationName.ToString()].OperationState; _jobRepository.PersistActivityProgress(activityProgress); }
public override async void ViewWillAppear(bool animated) { base.ViewWillAppear(animated); // Load this activity's progress from the database if available ActivityProgress progress = (await GetDatabaseManager()).GetProgress(DisplayedActivity); List <AppTask> appTasks = null; if (progress != null) { appTasks = JsonConvert.DeserializeObject <List <AppTask> >(progress.AppTaskJson, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }); } if (appTasks == null) { appTasks = new List <AppTask>(); foreach (LearningTask t in DisplayedActivity.LearningTasks) { appTasks.Add(new AppTask(t)); } } TaskViewSource source = new TaskViewSource(DisplayedActivity, appTasks, StartTask, ResultClicked, NameEdit); source.enteredName = progress?.EnteredUsername; TableView.Source = source; hiddenChildren = new Dictionary <int, List <AppTask> >(); AppTask[] temp = appTasks.ToArray(); foreach (AppTask parent in temp) { if (parent.TaskType.IdName == "INFO") { parent.IsCompleted = true; } if (parent.ChildAppTasks?.Count > 0) { hiddenChildren.Add(parent.Id, parent.ChildAppTasks); CheckForChildren(appTasks.IndexOf(parent)); } } TableView.ReloadData(); if (!loaded) { var suppress = PrepActivityFiles(); } }
public void PersistActivityProgress(ActivityProgress activityProgress) { _mongoDatabase .GetCollection <ActivityProgressKeyValue>(nameof(ActivityProgressKeyValue)) .ReplaceOne( filter: Builders <ActivityProgressKeyValue> .Filter.Eq("_id", nameof(ActivityProgressKeyValue)), replacement: new ActivityProgressKeyValue { LastUpdatedUtc = _clock.UtcNow, Value = activityProgress }, options: new UpdateOptions { IsUpsert = true }); }
public async Task <Activity> Sync() { var activity = new Activity(_clock.UtcNow); var activityProgress = default(ActivityProgress); _logger.LogInformation("Starting MP to HubSpot one-way sync operations (create new registrations first, followed by 2 update operations)."); try { activityProgress = _configurationService.GetCurrentActivityProgress(); if (activityProgress.ActivityState == ActivityState.Processing) { _logger.LogWarning("Job is already currently processing."); return(activity); } // set job processing state; get last successful sync dates _jobRepository.PersistActivityProgress(activityProgress = new ActivityProgress { ActivityState = ActivityState.Processing }); var operationDates = activity.PreviousOperationDates = _configurationService.GetLastSuccessfulOperationDates(); var ageGradeDeltaLog = default(ChildAgeAndGradeDeltaLogDto); Util.TryCatchSwallow(() => { // running this in advance of the create process with the express purpose of avoiding create/update race conditions when we consume the results for update PersistActivityProgress(activityProgress, OperationName.AgeGradeDataCalculationInMp, OperationState.Processing); activity.ChildAgeAndGradeCalculationOperation = CalculateAndPersistChildAgeGradeDataByHousehold(activity.PreviousOperationDates); ageGradeDeltaLog = activity.ChildAgeAndGradeCalculationOperation.AgeGradeDeltaLog; var operationContactCount = ageGradeDeltaLog.InsertCount + ageGradeDeltaLog.UpdateCount; var operationDuration = activity.ChildAgeAndGradeCalculationOperation.Execution.Duration; PersistActivityProgress(activityProgress, OperationName.AgeGradeDataCalculationInMp, operationContactCount: operationContactCount, operationDuration: operationDuration); operationDates.AgeAndGradeProcessDate = ageGradeDeltaLog.ProcessedUtc; operationDates.AgeAndGradeSyncDate = ageGradeDeltaLog.SyncCompletedUtc ?? default(DateTime); // go ahead and set in case there's nothing to do _jobRepository.PersistLastSuccessfulOperationDates(operationDates); PersistActivityProgress(activityProgress, OperationName.AgeGradeDataCalculationInMp, OperationState.Completed); }, () => { _logger.LogWarning("Age/grade calculation and persistence operation aborted."); PersistActivityProgress(activityProgress, OperationName.AgeGradeDataCalculationInMp, OperationState.Aborted); }); Util.TryCatchSwallow(() => { // sync newly registered contacts to hubspot PersistActivityProgress(activityProgress, OperationName.NewContactRegistrationSync, OperationState.Processing); activity.NewRegistrationSyncOperation = SyncNewRegistrations(activity.PreviousOperationDates.RegistrationSyncDate, activityProgress); if (_activityValidator.Validate(activity, ruleSet: RuleSetName.NewRegistrationSync).IsValid) { operationDates.RegistrationSyncDate = activity.NewRegistrationSyncOperation.Execution.StartUtc; _jobRepository.PersistLastSuccessfulOperationDates(operationDates); PersistActivityProgress(activityProgress, OperationName.NewContactRegistrationSync, OperationState.Completed, operationDuration: activity.NewRegistrationSyncOperation.Execution.Duration); } else { PersistActivityProgress(activityProgress, OperationName.NewContactRegistrationSync, OperationState.CompletedButWithIssues, operationDuration: activity.NewRegistrationSyncOperation.Execution.Duration); } }, () => { _logger.LogWarning("Sync new registrations operation aborted."); PersistActivityProgress(activityProgress, OperationName.NewContactRegistrationSync, OperationState.Aborted, operationDuration: activity.NewRegistrationSyncOperation.Execution.Duration); }); Util.TryCatchSwallow(() => { // sync core contact property updates to hubspot PersistActivityProgress(activityProgress, OperationName.CoreContactAttributeUpdateSync, OperationState.Processing); activity.CoreContactAttributeSyncOperation = SyncCoreUpdates(activity.PreviousOperationDates.CoreUpdateSyncDate, activityProgress); if (_activityValidator.Validate(activity, ruleSet: RuleSetName.CoreContactAttributeSync).IsValid) { operationDates.CoreUpdateSyncDate = activity.CoreContactAttributeSyncOperation.Execution.StartUtc; _jobRepository.PersistLastSuccessfulOperationDates(operationDates); PersistActivityProgress(activityProgress, OperationName.CoreContactAttributeUpdateSync, OperationState.Completed, operationDuration: activity.CoreContactAttributeSyncOperation.Execution.Duration); } else { PersistActivityProgress(activityProgress, OperationName.CoreContactAttributeUpdateSync, OperationState.CompletedButWithIssues, operationDuration: activity.CoreContactAttributeSyncOperation.Execution.Duration); } }, () => { _logger.LogWarning("Sync core updates operation aborted."); PersistActivityProgress(activityProgress, OperationName.CoreContactAttributeUpdateSync, OperationState.Aborted, operationDuration: activity.CoreContactAttributeSyncOperation.Execution.Duration); }); Util.TryCatchSwallow(() => { // sync age/grade data to hubspot contacts PersistActivityProgress(activityProgress, OperationName.AgeGradeDataSync, OperationState.Processing); activity.ChildAgeAndGradeSyncOperation = SyncChildAgeAndGradeData(ageGradeDeltaLog, activity.PreviousOperationDates.AgeAndGradeSyncDate); if (_activityValidator.Validate(activity, ruleSet: RuleSetName.ChildAgeGradeSync).IsValid) { if (ageGradeDeltaLog.InsertCount > 0 || ageGradeDeltaLog.UpdateCount > 0) { ageGradeDeltaLog.SyncCompletedUtc = operationDates.AgeAndGradeSyncDate = _ministryPlatformContactRepository.SetChildAgeAndGradeDeltaLogSyncCompletedUtcDate(); } _jobRepository.PersistLastSuccessfulOperationDates(operationDates); PersistActivityProgress(activityProgress, OperationName.AgeGradeDataSync, OperationState.Completed, activity.ChildAgeAndGradeSyncOperation.SuccessCount, activity.ChildAgeAndGradeSyncOperation.Execution.Duration); } else { PersistActivityProgress(activityProgress, OperationName.AgeGradeDataSync, OperationState.CompletedButWithIssues, operationDuration: activity.ChildAgeAndGradeSyncOperation.Execution.Duration); } }, () => { _logger.LogWarning("Sync age/grade data operation aborted."); PersistActivityProgress(activityProgress, OperationName.AgeGradeDataSync, OperationState.Aborted, operationDuration: activity.ChildAgeAndGradeSyncOperation.Execution.Duration); }); // reset sync job state PersistActivityProgress(activityProgress, ActivityState.Idle); return(activity); } catch (Exception exc) { _logger.LogError(CoreEvent.Exception, exc, "An exception occurred while syncing MP contacts to HubSpot."); PersistActivityProgress(activityProgress, ActivityState.Idle); throw; } finally // *** ALWAYS *** capture the activity, even if the job is already processing or an exception occurs { activity.ActivityProgress = activityProgress; activity.Execution.FinishUtc = _clock.UtcNow; PersistActivityProgress(activityProgress, activityDuration: activity.Execution.Duration); _activityCleaner.CleanUp(activity); if (_configurationService.PersistActivity()) { _jobRepository.PersistActivity(activity); } _logger.LogInformation("Exiting..."); } }
private void PersistActivityProgress(ActivityProgress activityProgress, ActivityState?activityState = null, string activityDuration = null) { activityProgress.ActivityState = activityState ?? activityProgress.ActivityState; activityProgress.Duration = activityDuration ?? activityProgress.Duration; _jobRepository.PersistActivityProgress(activityProgress); }
/// <summary> /// Capable of accommodating email address (unique identifier in HubSpot) change and other core contact attribute/property updates. /// Can also create a contact if it does not exist. /// </summary> private ActivitySyncOperation SyncCoreUpdates(DateTime lastSuccessfulSyncDate, ActivityProgress activityProgress) { var activity = new ActivitySyncOperation(_clock.UtcNow) { PreviousSyncDate = lastSuccessfulSyncDate }; try { _logger.LogInformation("Starting MP contact core updates to HubSpot one-way sync operation..."); var updates = _dataPrep.Prep(_ministryPlatformContactRepository.GetAuditedContactUpdates(lastSuccessfulSyncDate)); PersistActivityProgress(activityProgress, OperationName.CoreContactAttributeUpdateSync, operationContactCount: updates.Length); activity.SerialUpdateResult = _contactSyncer.SerialUpdate(updates); activity.SerialCreateResult = _contactSyncer.SerialCreate(activity.SerialUpdateResult.EmailAddressesDoNotExist.ToArray()); activity.SerialReconciliationResult = _contactSyncer.ReconcileConflicts(activity.SerialUpdateResult.EmailAddressesAlreadyExist.ToArray()); return(activity); } catch (Exception exc) { _logger.LogError(CoreEvent.Exception, exc, "An exception occurred while syncing MP contact core updates to HubSpot."); throw; } finally // *** ALWAYS *** capture the HubSpot API request count, even if an exception occurs { activity.Execution.FinishUtc = _clock.UtcNow; _jobRepository.PersistHubSpotApiDailyRequestCount(activity.HubSpotApiRequestCount, activity.Execution.StartUtc); } }
/// <summary> /// Handles create, update and reconciliation scenarios for MP CRM contacts identified as new registrants that ought to exist /// in the HubSpot CRM. /// </summary> private ActivitySyncOperation SyncNewRegistrations(DateTime lastSuccessfulSyncDate, ActivityProgress activityProgress) { var activity = new ActivitySyncOperation(_clock.UtcNow) { PreviousSyncDate = lastSuccessfulSyncDate }; try { _logger.LogInformation("Starting new MP registrations to HubSpot one-way sync operation..."); var newContacts = _ministryPlatformContactRepository.GetNewlyRegisteredContacts(lastSuccessfulSyncDate); // talk to MP PersistActivityProgress(activityProgress, OperationName.NewContactRegistrationSync, operationContactCount: newContacts.Count); activity.SerialCreateResult = _contactSyncer.SerialCreate(_dataPrep.Prep(newContacts)); // create in HubSpot activity.SerialUpdateResult = _contactSyncer.SerialUpdate(activity.SerialCreateResult.EmailAddressesAlreadyExist.ToArray()); // update in HubSpot activity.SerialReconciliationResult = _contactSyncer.ReconcileConflicts(activity.SerialUpdateResult.EmailAddressesAlreadyExist.ToArray()); return(activity); } catch (Exception exc) { _logger.LogError(CoreEvent.Exception, exc, "An exception occurred while syncing new MP contacts to HubSpot."); throw; } finally // *** ALWAYS *** capture the HubSpot API request count, even if an exception occurs { activity.Execution.FinishUtc = _clock.UtcNow; _jobRepository.PersistHubSpotApiDailyRequestCount(activity.HubSpotApiRequestCount, activity.Execution.StartUtc); } }
protected override async void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); string jsonData = Intent.GetStringExtra("JSON") ?? ""; learningActivity = JsonConvert.DeserializeObject <LearningActivity>(jsonData, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }); if (learningActivity == null) { using (var alert = new global::Android.Support.V7.App.AlertDialog.Builder(this)) { alert.SetTitle(Resource.String.ErrorTitle) .SetMessage(Resource.String.ErrorTitle) .SetOnDismissListener(new OnDismissListener(Finish)); alert.Show(); } return; } dbManager = await Storage.GetDatabaseManager(); // Load this activity's progress from the database if available ActivityProgress progress = dbManager.GetProgress(learningActivity); List <AppTask> appTasks = null; try { if (progress != null) { enteredName = progress.EnteredUsername; appTasks = JsonConvert.DeserializeObject <List <AppTask> >(progress.AppTaskJson); } } catch (Exception e) { Console.WriteLine(e.Message); Toast.MakeText(this, Resource.String.errorCache, ToastLength.Long).Show(); appTasks = null; } if (appTasks == null) { appTasks = learningActivity.LearningTasks.Select(t => new AppTask(t)).ToList(); } bool curatorControls = learningActivity.IsPublic && !learningActivity.Approved && dbManager.CurrentUser.Trusted; adapter = new TaskAdapter(this, learningActivity.Id, appTasks, learningActivity.Description, curatorControls, learningActivity.RequireUsername); adapter.ItemClick += OnItemClick; adapter.TextEntered += Adapter_TextEntered; adapter.ShowMedia += ShowMedia; adapter.Approved += Adapter_Approved; adapter.SpeakText += Adapter_SpeakText; adapter.ChangeName += Adapter_EditName; SetContentView(Resource.Layout.RecyclerViewActivity); recyclerView = FindViewById <RecyclerView>(Resource.Id.recyclerView); toolbar = FindViewById <global::Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar); SetSupportActionBar(toolbar); SupportActionBar.SetDisplayHomeAsUpEnabled(true); LoadHeaderImage(learningActivity.ImageUrl); SetupContent(); if (!string.IsNullOrWhiteSpace(enteredName)) { adapter.UpdateNames(enteredName); } }