/// <summary> /// Executes job tear down tasks. /// For the current job. once all autolinking taks are successfully done, we do the following: /// 1. Retrieve the deal by id /// 2. Update the deal stauts to : AutoLinkingComplete /// 3. Updat the deal /// 4. Schedule the job to which will tell Deal Server that deal is active /// </summary> /// <param name="executionResult"> /// The result of job startup tasks. /// </param> /// <param name="jobResult"> /// The result of job. /// </param> /// <returns> /// The result of the execution of the tear down tasks. /// </returns> public OrchestratedExecutionResult TearDown(OrchestratedExecutionResult executionResult) { Log.Information("AutoLinking Job Complete for Deal :{0}", DealId); Log.Information("Job Result :{0}", executionResult); if (executionResult == OrchestratedExecutionResult.Success) { CommerceContext context = new CommerceContext("Claim Discount For Existing Cards Job Context", CommerceWorkerConfig.Instance); // get the deal context[Key.GlobalDealId] = DealId; SharedDealLogic sharedDealLogic = new SharedDealLogic(context, CommerceOperationsFactory.DealOperations(context)); Deal deal = sharedDealLogic.RetrieveDeal(); //now upate deal status to mark autolinking complete context[Key.InitialDeal] = new Deal(deal); context[Key.Deal] = deal; deal.DealStatusId = DealStatus.AutoLinkingComplete; context[Key.PreviouslyRegistered] = true; sharedDealLogic.RegisterDeal(); //TODO:schedule the job to tell DS that deal should be activated, but now do it right here context[Key.GlobalDealId] = DealId; deal = sharedDealLogic.RetrieveDeal(); context[Key.InitialDeal] = new Deal(deal); context[Key.Deal] = deal; deal.DealStatusId = DealStatus.Activated; context[Key.PreviouslyRegistered] = true; sharedDealLogic.RegisterDeal(); } return(OrchestratedExecutionResult.Success); }
/// <summary> /// Executes the specified orchestrated job. /// </summary> /// <param name="tasksExecuted"> /// Receives the number of tasks executed. /// </param> /// <returns> /// The result of the execution of the job. /// </returns> public OrchestratedExecutionResult Execute(out int tasksExecuted) { OrchestratedExecutionResult result; tasksExecuted = 0; // Run startup tasks and propage their result. OrchestratedExecutionResult startUpResult = Job.StartUp(); result = startUpResult; OrchestratedExecutionResult jobResult = result; // If the startup tasks did not encounter an error, run the job. if (result == OrchestratedExecutionResult.Success) { if (Job.Asynchronous == true) { jobResult = ExecuteAsynchronous(out tasksExecuted); } else { jobResult = ExecuteSynchronous(out tasksExecuted); } result = jobResult; } return(result); }
/// <summary> /// Executes job tasks synchronously. /// </summary> /// <param name="tasksExecuted"> /// Receives the number of tasks executed by this job's tasks. /// </param> /// <returns> /// The result of the execution of this job's tasks. /// </returns> private OrchestratedExecutionResult ExecuteTasksSynchronous(out int tasksExecuted) { OrchestratedExecutionResult result = OrchestratedExecutionResult.Success; tasksExecuted = 0; if (Job.Tasks != null) { Log.Verbose("ScheduledJob ID {0}: Executing synchronous job type {1} tasks.", JobDetails.JobId, Job.GetType().Name); // Run each task in turn. foreach (IOrchestratedTask task in Job.Tasks) { OrchestratedExecutionResult taskResult = task.Execute(); tasksExecuted++; if (taskResult == OrchestratedExecutionResult.TerminalError) { result = OrchestratedExecutionResult.TerminalError; break; } else if (taskResult == OrchestratedExecutionResult.NonTerminalError) { result = OrchestratedExecutionResult.NonTerminalError; } } } return(result); }
/// <summary> /// Executes job's child jobs synchronously. /// </summary> /// <param name="tasksExecuted"> /// Receives the number of tasks executed by this job's child jobs. /// </param> /// <returns> /// The result of the execution of this job's child jobs. /// </returns> private OrchestratedExecutionResult ExecuteChildJobsSynchronous(out int tasksExecuted) { OrchestratedExecutionResult result = OrchestratedExecutionResult.Success; tasksExecuted = 0; if (Job.ChildJobs != null) { Log.Verbose("ScheduledJob ID {0}: Executing synchronous job type {1} child jobs.", JobDetails.JobId, Job.GetType().Name); foreach (IOrchestratedJob job in Job.ChildJobs) { JobOrchestrator jobOrchestrator = new JobOrchestrator(job, JobDetails, Log); OrchestratedExecutionResult jobResult = jobOrchestrator.Execute(out tasksExecuted); if (jobResult == OrchestratedExecutionResult.TerminalError) { result = jobResult; break; } else if (jobResult == OrchestratedExecutionResult.NonTerminalError) { result = jobResult; } } } return(result); }
/// <summary> /// Executes the task. /// </summary> /// <returns> /// The result of the execution of the task. /// </returns> public OrchestratedExecutionResult Execute() { OrchestratedExecutionResult result = OrchestratedExecutionResult.Success; try { // TODO: rename connection string, its no longer just FDC string connectionString = CloudConfigurationManager.GetSetting("Lomo.Commerce.Fdc.Blob.ConnectionString"); OfferRegistrationRecordBlobClient client = new OfferRegistrationRecordBlobClient(connectionString, Log); string fileName = BlobName(); byte[] contentBytes = Encoding.ASCII.GetBytes(OfferRegistrationRecord); MemoryStream ms = new MemoryStream(contentBytes); ms.Position = 0; client.UploadAsync(ms, fileName).Wait(); JobDetails.Payload[AmexMerchantId] = AmexMerchantIdMarker; } catch (Exception exception) { Log.Warning("Unexpected error encountered during AmexOfferBlobUploadTask execution. Job will be retried. " + "Exception:\r\n{0}", exception); result = OrchestratedExecutionResult.NonTerminalError; } return(result); }
/// <summary> /// Applies the Earn reward according to RewardPayoutRecord parameters. /// </summary> /// <returns></returns> public OrchestratedExecutionResult Apply() { OrchestratedExecutionResult result = OrchestratedExecutionResult.NonTerminalError; CommerceContext context = new CommerceContext("Updating reward status", CommerceWorkerConfig.Instance); context[Key.RewardPayoutId] = RewardPayoutRecord.RewardPayoutId; context[Key.RewardPayoutStatus] = RewardPayoutStatus.NoEligibleUser; string actionDescription = String.Empty; if (RewardPayoutRecord.PayeeType == PayeeType.User) { if (RewardPayoutRecord.PayeeId != Guid.Empty) { if (RewardPayoutRecord.Rescinded == false) { result = OrchestratedExecutionResult.Success; context[Key.RewardPayoutStatus] = RewardPayoutStatus.Paid; actionDescription = "was paid"; } else { context[Key.RewardPayoutStatus] = RewardPayoutStatus.Rescinded; Log.Information("A rescinded reward cannot be paid out."); actionDescription = "could not be paid because the reward has been rescinded"; } } else { Log.Warning("Payee ID cannot be Guid.Empty."); actionDescription = "could not be paid because no eligible user could be found"; } } else { Log.Warning("Earn Rewards cannot be applied to payees of type {0}.", RewardPayoutRecord.PayeeType); actionDescription = String.Format("could not be paid because payees of type {0} cannot receive Earn Rewards", RewardPayoutRecord.PayeeType); } Log.Verbose("Updating reward payout record status to indicate the reward {0}.", actionDescription); IRewardOperations rewardOperations = CommerceOperationsFactory.RewardOperations(context); ResultCode resultCode = rewardOperations.UpdateRewardPayoutStatus(); if (resultCode != ResultCode.Success && resultCode != ResultCode.PayoutStatusTooAdvanced) { result = OrchestratedExecutionResult.NonTerminalError; Log.Warning("{0} call unsuccessfully processed.\r\n\r\nResultCode: {1}\r\n\r\nExplanation: {2}", (int)resultCode, context.ApiCallDescription, resultCode, ResultCodeExplanation.Get(resultCode)); } return(result); }
/// <summary> /// Executes the task. /// </summary> /// <returns> /// The result of the execution of the task. /// </returns> public OrchestratedExecutionResult Execute() { OrchestratedExecutionResult result = OrchestratedExecutionResult.NonTerminalError; // Call the MBI endpoint to claim the deal. Uri uri = new Uri(String.Concat((string)CommerceWorkerConfig.Instance.MbiServiceAuthority, (string)CommerceWorkerConfig.Instance.ServiceClaimedDealsControllerEndpoint)); HttpStatusCode httpStatusCode = HttpStatusCode.Forbidden; string response = String.Empty; try { response = RestServiceClient.CallRestService(uri, RestServiceVerbs.Post, RestServiceContentTypes.Json, General.SerializeJson(ClaimDealPayload), RestServiceClient.ObtainAuthorizationToken("claimeddeals"), out httpStatusCode); } catch (WebException ex) { Log.Warning("An unknown exception was thrown during the service call. Job will be retried. " + "Exception:\r\n{0}", ex); } // If a response was received, try to deserialize the response body into a ClaimDealResponse. if (String.IsNullOrWhiteSpace(response) == false) { ClaimDealResponse claimDealResponse = null; try { claimDealResponse = General.DeserializeJson <ClaimDealResponse>(response); } catch (JsonReaderException) { claimDealResponse = null; } // If we have a deserialized response, process it. if (claimDealResponse != null) { result = ProcessResponse(claimDealResponse, httpStatusCode); } // Otherwise, log the call response and try again. else { Log.Warning("Unexpected service response encountered during ClaimDealTask execution. Job will be retried. " + "Response:\r\n{0}", response); result = OrchestratedExecutionResult.NonTerminalError; } } return(result); }
/// <summary> /// Executes job tear down tasks. /// </summary> /// <param name="executionResult"> /// The result of job startup tasks. /// </param> /// <param name="jobResult"> /// The result of job. /// </param> /// <returns> /// The result of the execution of the tear down tasks. /// </returns> public OrchestratedExecutionResult TearDown(OrchestratedExecutionResult executionResult) { if (executionResult == OrchestratedExecutionResult.Success) { CommerceContext context = new CommerceContext("Claim Discount For Existing Cards Job Context", CommerceWorkerConfig.Instance); context[Key.UserId] = UserId; context[Key.CardId] = CardId; Log.Information("Have to send notification here, userid :{0}, cardid :{1}", UserId, CardId); // send add card notification here Notify notify = new NotifyAddCard(context); Task.Run(new Action(notify.SendNotification)); } return(OrchestratedExecutionResult.Success); }
/// <summary> /// Clean up the job state /// </summary> /// <param name="executionResult"> /// Execution Result of the job /// </param> /// <returns></returns> public OrchestratedExecutionResult Cleanup(OrchestratedExecutionResult executionResult) { OrchestratedExecutionResult result = executionResult; OrchestratedExecutionResult tearDownResult = Job.TearDown(executionResult); if (tearDownResult == OrchestratedExecutionResult.TerminalError) { result = OrchestratedExecutionResult.TerminalError; } else if (tearDownResult == OrchestratedExecutionResult.NonTerminalError && result != OrchestratedExecutionResult.TerminalError) { result = OrchestratedExecutionResult.NonTerminalError; } return(result); }
/// <summary> /// Executes job tasks and child jobs synchronously. /// </summary> /// <param name="tasksExecuted"> /// Receives the number of tasks executed by this job and all child jobs. /// </param> /// <returns> /// The result of the execution of this job and all child jobs. /// </returns> private OrchestratedExecutionResult ExecuteSynchronous(out int tasksExecuted) { OrchestratedExecutionResult result = OrchestratedExecutionResult.Success; if (Job.TasksFirst == true) { Log.Verbose("ScheduledJob ID {0}: Executing synchronous job type {1}, tasks first.", JobDetails.JobId, Job.GetType().Name); result = ExecuteSynchronous(ExecuteTasksSynchronous, ExecuteChildJobsSynchronous, out tasksExecuted); } else { Log.Verbose("ScheduledJob ID {0}: Executing synchronous job type {1}, child jobs first.", JobDetails.JobId, Job.GetType().Name); result = ExecuteSynchronous(ExecuteChildJobsSynchronous, ExecuteTasksSynchronous, out tasksExecuted); } return(result); }
/// <summary> /// Executes the task. /// </summary> /// <returns> /// The result of the execution of the task. /// </returns> public OrchestratedExecutionResult Execute() { OrchestratedExecutionResult result = OrchestratedExecutionResult.NonTerminalError; switch (RewardPayoutRecord.RewardType) { case RewardType.Undefined: case RewardType.StatementCredit: Log.Verbose("Updating reward payout record status to indicate the reward is pending."); CommerceContext context = new CommerceContext("Updating reward status", CommerceWorkerConfig.Instance); context[Key.RewardPayoutId] = RewardPayoutRecord.RewardPayoutId; context[Key.RewardPayoutStatus] = RewardPayoutStatus.Pending; IRewardOperations rewardOperations = CommerceOperationsFactory.RewardOperations(context); ResultCode resultCode = rewardOperations.UpdateRewardPayoutStatus(); if (resultCode != ResultCode.Success) { result = OrchestratedExecutionResult.NonTerminalError; Log.Warning("{0} call unsuccessfully processed.\r\n\r\nResultCode: {1}\r\n\r\nExplanation: {2}", (int)resultCode, context.ApiCallDescription, resultCode, ResultCodeExplanation.Get(resultCode)); } else { result = OrchestratedExecutionResult.Success; } break; case RewardType.EarnCredit: ApplyEarnCredit applyEarnCredit = new ApplyEarnCredit(RewardPayoutRecord, Log); result = applyEarnCredit.Apply(); break; default: Log.Error("Invalid reward type {0} in reward payout record.", null, RewardPayoutRecord.RewardType); break; } return(result); }
/// <summary> /// Executes job tasks and child jobs synchronously. /// </summary> /// <param name="firstStep"> /// First synchronous step to execute, based on value of Job.TasksFirst. /// </param> /// <param name="secondStep"> /// Second synchronous step to execute, based on value of Job.TasksFirst. /// </param> /// <param name="tasksExecuted"> /// Receives the number of tasks executed by this job and all child jobs. /// </param> /// <returns> /// The result of the execution of this job and all child jobs. /// </returns> private static OrchestratedExecutionResult ExecuteSynchronous(SynchronousExecutionStep firstStep, SynchronousExecutionStep secondStep, out int tasksExecuted) { OrchestratedExecutionResult result = OrchestratedExecutionResult.Success; tasksExecuted = 0; int stepTasksExecuted; OrchestratedExecutionResult stepResult = firstStep(out stepTasksExecuted); tasksExecuted += stepTasksExecuted; if (stepResult == OrchestratedExecutionResult.TerminalError) { result = OrchestratedExecutionResult.TerminalError; } else if (stepResult == OrchestratedExecutionResult.NonTerminalError) { result = OrchestratedExecutionResult.NonTerminalError; } if (result != OrchestratedExecutionResult.TerminalError) { stepResult = secondStep(out stepTasksExecuted); tasksExecuted += stepTasksExecuted; if (stepResult == OrchestratedExecutionResult.TerminalError) { result = OrchestratedExecutionResult.TerminalError; } else if (stepResult == OrchestratedExecutionResult.NonTerminalError) { result = OrchestratedExecutionResult.NonTerminalError; } } return(result); }
/// <summary> /// Executes job tear down tasks. /// </summary> /// <param name="executionResult"> /// The result of job startup tasks. /// </param> /// <returns> /// The result of the execution of the tear down tasks. /// </returns> public OrchestratedExecutionResult TearDown(OrchestratedExecutionResult executionResult) { return(OrchestratedExecutionResult.Success); }
/// <summary> /// Executes job tasks and child jobs asynchronously. /// </summary> /// <param name="tasksExecuted"> /// Receives the number of tasks executed by this job and all child jobs. /// </param> /// <returns> /// The result of the execution of this job and all child jobs. /// </returns> private OrchestratedExecutionResult ExecuteAsynchronous(out int tasksExecuted) { OrchestratedExecutionResult result = OrchestratedExecutionResult.Success; tasksExecuted = 0; Log.Verbose("ScheduledJob ID {0}: Executing job type {1} tasks and child jobs asynchronously.", JobDetails.JobId, Job.GetType().Name); // Determine how many item will execute while running this job. int itemCount = 0; if (Job.Tasks != null) { itemCount = Job.Tasks.Count; } if (Job.ChildJobs != null) { itemCount += Job.ChildJobs.Count; } // If there are any items to execute, do so asynchronously. if (itemCount > 0) { // Spin up threads to execute the tasks and child jobs. List <Task> executors = new List <Task>(itemCount); ConcurrentDictionary <Guid, Tuple <int, OrchestratedExecutionResult> > itemTaskResults = new ConcurrentDictionary <Guid, Tuple <int, OrchestratedExecutionResult> >(itemCount, itemCount); if (Job.Tasks != null) { IEnumerable <OrchestratedExecutionResult> results = ParallelTaskThrottler.Instance.Run(Job.Tasks); foreach (OrchestratedExecutionResult orchestratedExecutionResult in results) { itemTaskResults[Guid.NewGuid()] = new Tuple <int, OrchestratedExecutionResult>(1, orchestratedExecutionResult); } } if (Job.ChildJobs != null) { foreach (IOrchestratedJob job in Job.ChildJobs) { JobOrchestrator jobOrchestrator = new JobOrchestrator(job, JobDetails, Log); executors.Add(Task.Factory.StartNew(() => { int childTasksExecuted; OrchestratedExecutionResult childResult = jobOrchestrator.Execute(out childTasksExecuted); itemTaskResults[Guid.NewGuid()] = new Tuple <int, OrchestratedExecutionResult>(childTasksExecuted, childResult); })); } } // Wait until all threads have completed their work. Task.WaitAll(executors.ToArray()); // Tally up the completed tasks and get overall result. foreach (Guid key in itemTaskResults.Keys) { Tuple <int, OrchestratedExecutionResult> itemTaskResult = itemTaskResults[key]; tasksExecuted += itemTaskResult.Item1; if (itemTaskResult.Item2 == OrchestratedExecutionResult.TerminalError) { result = OrchestratedExecutionResult.TerminalError; } else if (itemTaskResult.Item2 == OrchestratedExecutionResult.NonTerminalError && result != OrchestratedExecutionResult.TerminalError) { result = OrchestratedExecutionResult.NonTerminalError; } } } return(result); }