/// <summary> /// Ctor for runner /// </summary> /// <param name="jobFactory"> /// Job Factory to get implementation of the job /// </param> /// <param name="scheduler"> /// Scheduler /// </param> /// <param name="commerceConfig"> /// Config /// </param> /// <param name="log"> /// Logger /// </param> public OrchestratedJobRunner( Func <ScheduledJobDetails, IScheduler, CommerceLog, IOrchestratedJob> jobFactory, IScheduler scheduler, CommerceConfig commerceConfig, CommerceLog log) { JobFactory = jobFactory; CommerceConfig = commerceConfig; Log = log; Scheduler = scheduler; }
/// <summary> /// Obtains the ANID for the specified canonical user ID. /// </summary> /// <param name="userId"> /// The canonical user ID for whose ANID to obtain. /// </param> /// <param name="commerceConfig"> /// The configuration instance to use. /// </param> /// <returns> /// The ANID for the specified user. /// </returns> private static string GetAnidFromUserId(Guid userId, CommerceConfig commerceConfig) { string puid = String.Empty; User user = PartnerFactory.UsersDal(commerceConfig).GetUserByUserId(userId); if (user != null) { puid = user.MsId; } return(CommerceAnalyticsFactory.AnalyticsUserInfo(commerceConfig).GetAnidFromPuid(puid)); }
/// <summary> /// Creates a new instance for the Commerce Context class. /// You can specify the config to use. /// </summary> /// <param name="apiCallDescription"> /// The call description for the API in which this context object is used. /// </param> /// <param name="config"> /// The config to use to get configuration info from. /// </param> public CommerceContext(string apiCallDescription, CommerceConfig config) { ApiCallDescription = apiCallDescription; Config = config; if (config != null) { Log = new CommerceLog(Guid.NewGuid(), config.LogVerbosity, General.CommerceLogSource); CommerceLog.Config = config; } PerformanceInformation = new PerformanceInformation(); Values = new Hashtable(); }
/// <summary> /// Gets the object to use to perform user services client operations. /// </summary> /// <param name="commerceConfig"> /// The CommerceConfig object to use to determine if mock partner dependencies are being used. /// </param> /// <param name="userServicesUri"> /// The Uri at which the User Services can be found. /// </param> /// <returns> /// The IUserServicesClient instance to use. /// </returns> /// <exception cref="ArgumentNullException"> /// Parameter commerceConfig cannot be null. /// </exception> public static IUserServicesClient UserServicesClient(Uri userServicesUri, CommerceConfig commerceConfig) { if (commerceConfig == null) { throw new ArgumentNullException("commerceConfig", "Parameter commerceConfig cannot be null."); } IUserServicesClient result = new UserServiceClient(userServicesUri); if (commerceConfig.UseMockPartnerDependencies == true) { result = LateBinding.BuildObjectFromLateBoundAssembly <IUserServicesClient>("MockUserServicesClient", LateBoundMocksAssemblyTypes); } return(result); }
public static void CreateLogInstance(SourceLevels logVerbosity, bool forceEventLog, string source, CommerceConfig configuration) { // Setup the log. string deploymentId = null; string instanceId = null; TraceListener traceListener = null; //if (General.RunningInAzure == true) //{ // deploymentId = RoleEnvironment.DeploymentId; // instanceId = RoleEnvironment.CurrentRoleInstance.Id; // traceListener = new DiagnosticMonitorTraceListener { Name = "AzureDiagnostics" }; //} CreateLogInstance(deploymentId, instanceId, traceListener, logVerbosity, forceEventLog, source, configuration); }
/// <summary> /// Gets the object to use to perform operations on users. /// </summary> /// <param name="commerceConfig"> /// The CommerceConfig object to use to determine if mock partner dependencies are being used. /// </param> public static IUsersDal UsersDal(CommerceConfig commerceConfig) { if (commerceConfig == null) { throw new ArgumentNullException("commerceConfig", "Parameter commerceConfig cannot be null."); } if (usersDal == null) { usersDal = new UsersDal(); if (commerceConfig.UseMockPartnerDependencies == true) { usersDal = LateBinding.BuildObjectFromLateBoundAssembly <IUsersDal>("MockUsersDal", LateBoundMocksAssemblyTypes); } } return(usersDal); }
/// <summary> /// Gets the object for azure table to add certain warnings /// </summary> /// <param name="config"> /// The configuration to use to get settings. /// </param> /// <returns> /// The IAzureTable instance to use. /// </returns> /// <exception cref="ArgumentNullException"> /// Parameter config cannot be null. /// </exception> public static IAzureTable AzureTable(CommerceConfig config) { if (config == null) { throw new ArgumentNullException("config", "Parameter config cannot be null."); } if (azureTable == null) { azureTable = new AzureTable(); if (config.UseMockPartnerDependencies == true) { azureTable = LateBinding.BuildObjectFromLateBoundAssembly <IAzureTable>("MockAzureTable", LateBoundMocksAssemblyTypes); } } return(azureTable); }
/// <summary> /// Get the object to add analytics data /// </summary> /// <param name="commerceConfig"> /// The CommerceConfig object to use to determine if mock partner dependencies are being used. /// </param> /// <returns> /// The IAnalytics client instance to use. /// </returns> /// <exception cref="ArgumentNullException"> /// Parameter commerceConfig cannot be null. /// </exception> public static IAnalyticsClient AnalyticsClient(CommerceConfig commerceConfig) { if (commerceConfig == null) { throw new ArgumentNullException("commerceConfig", "Parameter commerceConfig cannot be null."); } if (analyticsClient == null) { analyticsClient = new AnalyticsClient(); if (commerceConfig.UseMockPartnerDependencies == true) { analyticsClient = LateBinding.BuildObjectFromLateBoundAssembly <IAnalyticsClient>("MockAnalyticsClient", LateBoundMocksAssemblyTypes); } } return(analyticsClient); }
/// <summary> /// Adds a redemption event to the analytics. /// </summary> /// <param name="userId"> /// The canonical user ID to associate with the event. /// </param> /// <param name="redemptionEventId"> /// The ID of this redemption event. /// </param> /// <param name="correlationId"> /// The ID of the event to which this event will be correlated. /// </param> /// <param name="dealId"> /// The ID of the deal being redeemed. /// </param> /// <param name="currency"> /// The currency involved in the transaction in which the deal was redeeemed. /// </param> /// <param name="authorizationAmount"> /// The authorization amount in the transaction in which the deal was redeemed. /// </param> /// <param name="discountAmount"> /// The discount amount from the transaction in which the deal was redeemed. /// </param> /// <param name="discountId"> /// The ID of the discount within the deal that was specifically redeemed. /// </param> /// <param name="partnerMerchantId"> /// The ID of the merchant as assigned by the processing partner. /// </param> /// <param name="config"> /// Optional configuration /// </param> public static void AddRedemptionEvent(Guid userId, Guid redemptionEventId, Guid correlationId, Guid dealId, string currency, int authorizationAmount, int discountAmount, Guid discountId, string partnerMerchantId, CommerceConfig config = null) { if (config == null) { config = CommerceServiceConfig.Instance; } if (config.EnableServiceHealth == true) { AnalyticsClient.Payloads.DealRedemptionPayload payload = new AnalyticsClient.Payloads.DealRedemptionPayload { AuthorizationAmount = authorizationAmount, Currency = currency, DiscountAmount = discountAmount, DiscountId = discountId, PartnerMerchantId = partnerMerchantId }; AnalyticsClient.AnalyticsItem item = new AnalyticsClient.AnalyticsItem { Action = AnalyticsClient.Actions.Actions.RedeemedDeal, UserId = GetAnidFromUserId(userId, config), ClientId = AnalyticsClientId, EventId = redemptionEventId, ParentEventId = correlationId, DealId = dealId, JPayload = JObject.FromObject(payload) }; PartnerFactory.AnalyticsClient(config).Add(item); } }
/// <summary> /// Gets the Mock Scheduler /// </summary> /// <param name="queueName"> /// Queue Name /// </param> /// <param name="tableName"> /// Table Name /// </param> /// <returns> /// The IScheduler instance to use. /// </returns> /// <exception cref="ArgumentNullException"> /// Parameter config cannot be null. /// </exception> public static IScheduler Scheduler(string queueName, string tableName, CommerceConfig config) { if (config == null) { throw new ArgumentNullException("config", "Parameter config cannot be null."); } if (scheduler == null) { scheduler = SchedulerFactory.GetScheduler(CloudConfigurationManager.GetSetting("Lomo.Commerce.Scheduler.ConnectionString"), queueName, tableName); if (config.UseMockPartnerDependencies == true) { scheduler = LateBinding.BuildObjectFromLateBoundAssembly <IScheduler>("MockScheduler", LateBoundMocksAssemblyTypes); } } return(scheduler); }
/// <summary> /// Adds a log entry to the log table /// </summary> /// <param name="requestId"> /// Request Id that uniquely identifies the service request to the commerce server /// </param> /// <param name="resultCode"> /// Result code of the service invocation /// </param> /// <param name="resultSummary"> /// Summary explanation of the result code /// </param> /// <param name="config"> /// The configuration to use to get settings. /// </param> public static void Add(Guid requestId, ResultCode resultCode, string resultSummary, CommerceConfig config) { try { if (config == null) { throw new ArgumentNullException("config", "Parameter config cannot be null."); } if (config.EnableServiceHealth == true) { DashboardLogEntity logEntity = new DashboardLogEntity(requestId, resultCode.ToString(), resultSummary); PartnerFactory.AzureTable(config).InsertEntity(logEntity); } } catch (Exception exception) { Log.Error(exception, string.Format("Unable to log the data to azure table : {0} ", exception.Message)); } }
/// <summary> /// Creates the appropriate Log instance for the current environment. /// </summary> /// <param name="deploymentId"> /// * If running in Azure, the ID of the deployment that created the VM hosting this application /// * Else null. /// </param> /// <param name="instanceId"> /// * If running in Azure, the ID of the role instance currently hosting this application /// * Else null. /// </param> /// <param name="traceListener"> /// * If running in Azure, the Azure diagnostic monitor trace listener to use for the log. /// * Else null. /// </param> /// <param name="logVerbosity"> /// Specified the verbosity level for entries to commit to the log. /// </param> /// <param name="forceEventLog"> /// Specifies whether to force use of the event log instead of other logging mechanisms. /// </param> /// <param name="source"> /// The source under which to log events. /// </param> /// <param name="configuration"> /// The configuration to use to get settings. /// </param> internal static void CreateLogInstance(string deploymentId, string instanceId, TraceListener traceListener, SourceLevels logVerbosity, bool forceEventLog, string source, CommerceConfig configuration) { lock (CreateLogInstanceLock) { string dashboardConnectionKey; if (General.RunningInAzure == true) { // If the event log is not set to be used regardless of environment, create a TraceLog and a listener to // funnel log entries into central storage. if (forceEventLog == false) { Log.Instance = new TraceLog(new List <TraceListener> { traceListener }, logVerbosity) { Source = source }; } else { Log.Instance = new EventLogLog(logVerbosity) { Source = source }; } // Set the server ID to a value useful in Azure. RequestInformationExtensions.ServerId = String.Format("{0}_{1}", deploymentId, instanceId.Substring(instanceId.LastIndexOf("_", StringComparison.OrdinalIgnoreCase) + 1)); dashboardConnectionKey = CloudConfigurationManager.GetSetting(DashboardConnectionString); } else { Log.Instance = new EventLogLog(logVerbosity) { Source = source }; dashboardConnectionKey = ConfigurationManager.AppSettings[DashboardConnectionString]; } // Initialize the dashboard table into which a subset of warnings will be logged. if (String.IsNullOrEmpty(dashboardConnectionKey) == false) { CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(dashboardConnectionKey); PartnerFactory.AzureTable(configuration).Initialize(cloudStorageAccount, DashboardTableName, new ExponentialRetry(TimeSpan.FromSeconds(5), 1)); } // Flag log instance as set so CommerceLog won't attempt to create one. CommerceLog.LogInstanceSet = true; CommerceLog.Config = configuration; } }
public static ISftpClient SftpClient(string username, string password, string uri, CommerceConfig config) { if (config == null) { throw new ArgumentNullException("config", "Parameter config cannot be null."); } if (sftpClient == null) { sftpClient = new DefaultSftpClient(username, password, uri); if (config.UseMockPartnerDependencies) { sftpClient = LateBinding.BuildObjectFromLateBoundAssembly <ISftpClient>("MockSftpClient", LateBoundMocksAssemblyTypes); } } return(sftpClient); }
/// <summary> /// Gets the object to use to perform operations on users. /// </summary> /// <param name="performanceInformation"> /// The object through which performance information can be added and obtained. /// </param> /// <param name="visaInvokerOverride"> /// The specific VisaInvoker object to return, if not null. /// </param> /// <param name="config"> /// The config object. /// </param> public static IVisaInvoker BuildVisaInvoker(PerformanceInformation performanceInformation, IVisaInvoker visaInvokerOverride, CommerceConfig config) { IVisaInvoker result = new VisaInvoker(); result.PerformanceInformation = performanceInformation; if (config.UseMockPartnerDependencies) { result = LateBinding.BuildObjectFromLateBoundAssembly <IVisaInvoker>("MockVisaInvoker", LateBoundMocksAssemblyTypes); } // If the override object is not null, return it instead. if (visaInvokerOverride != null) { result = visaInvokerOverride; } return(result); }
/// <summary> /// Invokes a call to a partner API method, retrying if needed. /// </summary> /// <param name="context"> /// The context of the operation. /// </param> /// <param name="invoker"> /// The function to call to invoke the partner API method. /// </param> /// <param name="terminalCodes"> /// Set of terminal result codes on which we should not retry. /// For example, if result is invalid card, one should not need to try again. /// </param> /// <param name="partner"> /// Optionally, callers can specify their partner. /// </param> /// <param name="retryOnTransientErrorOnly"> /// Optionally, settting this as true will retry on transientErrorOnly which in this case mean that if there is an exception /// </param> internal static async Task <ResultCode> InvokePartner(CommerceContext context, Func <Task <ResultCode> > invoker, HashSet <ResultCode> terminalCodes = null, Partner partner = Partner.None, bool retryOnTransientErrorOnly = false) { ResultCode result = ResultCode.None; // initialize terminal codes if not provided if (terminalCodes == null) { terminalCodes = new HashSet <ResultCode>(); terminalCodes.Add(ResultCode.Success); terminalCodes.Add(ResultCode.Created); } // Invoke the partner, retrying if needed. CommerceConfig config = context.Config ?? CommerceServiceConfig.Instance; int tryCount = 0; int maxRetries = config.MaxPartnerRetries; int retryLatency = config.InitialPartnerRetryLatency; do { try { tryCount++; result = await invoker().ConfigureAwait(false); //we consider transient error as a runtime exception while calling external API. Since there is no exception and retryOnTransientErrorOnly is set //to true we will break if (retryOnTransientErrorOnly) { break; } } catch (Exception ex) { bool firstDataBadRequest = partner == Partner.FirstData && ex.Message.Contains("(400) Bad Request"); string message = String.Format("{0} call encountered an error.", context.ApiCallDescription); if (tryCount <= maxRetries) { if (firstDataBadRequest == false) { context.Log.Critical(message, ex); } else { context.Log.Warning(String.Format("First Data {0}: (400) Bad Request detected. This is common because of clock skew and should resolve itself when the job is retried.", message)); } } else { throw; } } // If a rety is needed, wait a short but increasingly lengthy time before proceeding. if (tryCount <= maxRetries && !terminalCodes.Contains(result)) { context.Log.Verbose("Waiting {0} milliseconds before retrying partner invocation.", retryLatency); Thread.Sleep(retryLatency); retryLatency *= 2; } }while (tryCount <= maxRetries && result != ResultCode.Success && result != ResultCode.Created); return(result); }
/// <summary> /// Initializes the Analytics client /// </summary> /// <param name="commerceConfig"> /// The CommerceConfig object to use during initialization. /// </param> public static void Initialize(CommerceConfig commerceConfig) { PartnerFactory.AnalyticsClient(commerceConfig).Initialize("commerce"); }
/// <summary> /// Get a Job Runner <see cref="IJobRunner"/> /// </summary> /// <param name="jobDetails"> /// Job Details /// </param> /// <param name="scheduler"> /// Scheduler to use /// </param> /// <param name="commerceConfig"> /// Configuration /// </param> /// <param name="log"> /// Logger /// </param> /// <returns> /// Instance of a runner /// </returns> public static IJobRunner Runner(ScheduledJobDetails jobDetails, IScheduler scheduler, CommerceConfig commerceConfig, CommerceLog log) { if (jobDetails.Orchestrated) { return(new OrchestratedJobRunner(OrchestratedJobFactory.Create, scheduler, commerceConfig, log)); } return(new SimpleJobRunner(ScheduledJobFactory.GetJobByType, log, scheduler)); }