/// <summary> /// Invokes method in proxied service passing parameters specified. /// Optionally, persists and retries the method until successful. /// </summary> /// <param name="method">MethodInfo containing method to invoke</param> /// <param name="wifiOnly">Indicates if message is to be sent via WiFi only</param> /// <param name="recurringId">Will mark a recurring message with and Id that can be used to stop the call from recurring. /// Method must have RecurringAttribute or id will not be record. Pass Guid.Empty if you don't wish to set this value.</param> /// <param name="parameters">Optional list of parameters to include in method invocation</param> /// <returns>If call is recurring will return an id that can be used to stop to recurrence; Otherwise will return null.</returns> public Guid CallService(MethodInfo method, bool wifiOnly, Guid recurringId, params Object[] parameters) { _logger.Debug("Entered MethodInfo ServiceProxy.CallService"); if (method == null) { _logger.Warn("Null method provided. Call skipped."); throw new ArgumentException("Method value null"); } var sc = new ServiceCall { Target = ProxiedService, Method = method, MethodName = method.Name, Parameters = parameters, UseGetResult = method.GetCustomAttributes(typeof(UseIResultAttribute), false).Any(), RecurringMessageId = (method.GetCustomAttributes(typeof(RecurringAttribute), false).Any()) ? (recurringId == Guid.Empty ? NewRecurringId : recurringId) : Guid.Empty, WifiOnly = wifiOnly }; _logger.Debug("In ServiceProxy.CallService, about to call Create"); Create(sc); return(sc.RecurringMessageId); }
/// <summary> /// Saves service call into the database.. /// </summary> /// <param name="serviceCall">Service call that you would like to save to the database</param> private void Create(ServiceCall serviceCall) { var message = new Message { Text = JsonConvert.SerializeObject(serviceCall), Type = serviceCall.GetType().FullName, Status = MessageStatus.Incomplete, WifiOnly = serviceCall.WifiOnly, RecurringId = serviceCall.RecurringMessageId }; if (serviceCall.Parameters != null) { for (var index = 0; index < serviceCall.Parameters.Length; index++) { MessageParameter parameter = null; if (serviceCall.Parameters[index] != null) { parameter = new MessageParameter { Sequence = index + 1, Type = serviceCall.Parameters[index].GetType().FullName, Text = JsonConvert.SerializeObject(serviceCall.Parameters[index]) }; _logger.Debug("in ServiceProxy.Create, paramType is: " + parameter.Type); _logger.Debug("in ServiceProxy.Create, paramText is: " + parameter.Text); } message.Parameters.Add(parameter); } } try { _logger.Debug("in ServiceProxy.Create, about to invoke lock"); Messages.Instance.AddNewMessage(message); serviceCall.MessageId = message.Id; _logger.Debug("in ServiceProxy.Create, AddNewMessage completed"); } catch (Exception e) { _logger.Error("Error Creating Message", e); } }
/// <summary> /// Marks messages as transmitting and increments the retry counter. /// Invokes the service call and connects the completion event. /// </summary> /// <param name="call"></param> private void CallService(ServiceCall call) { var targetMethod = call.Method; _logger.Debug("Started"); try { _logger.Debug($"Operating on ServiceCall: {call}"); _logger.Debug($"Call target: {call.Target}"); if (targetMethod == null) { _logger.Debug("targetMethod was null, attempting to get RuntimeMethod"); var types = Util.GetTypes(call.Parameters); _logger.Debug($"Looking for method: {call.MethodName}"); _logger.Debug($"Target: {call.Target.GetType().FullName}"); targetMethod = call.Target.GetType().GetRuntimeMethod(call.MethodName, types); } if (targetMethod != null) { _logger.Debug("Entering lock"); _logger.Info($"Target Method: {targetMethod.Name}"); var message = Messages.Instance.GetMessage(call.MessageId); Messages.Instance.IncrementRetry(message); Messages.Instance.MarkMessage(message, MessageStatus.Transmitting); call.CallCompleteEventHandler += sc_CallCompleteEventHandler; _logger.Debug($"CallService: Id: {call.MessageId}, Method {call.MethodName}"); _logger.Debug("in ServiceProxy.Create, invoking call.InvokeServiceMethodAsync"); Task.Run(async() => await call.InvokeServiceMethodAsync()).ConfigureAwait(false); _logger.Debug("Finished"); } else { var methods = call.Target.GetType().GetRuntimeMethods(); if (methods != null) { foreach (var method in methods) { _logger.Debug($"Found method: {method.Name}"); } } else { _logger.Debug("No runtime methods found!"); } _logger.Info($"Ignoring call to method {call.MethodName}, not contained in target {call.Target.GetType()}"); } } catch (Exception ex) { _logger.Error("Failed to mark message for transmit : " + ex.Message, ex); } finally { if (targetMethod != null) { _logger.Debug("Exited lock"); } } }