/// <summary> /// Call all subscribers in parallel and wait for all to complete. /// </summary> /// <typeparam name="T">The type of the results.</typeparam> /// <param name="ServerTimestamp">The timestamp of the event.</param> /// <param name="OCPIAPI">The sending OCPI/HTTP API.</param> /// <param name="Request">The incoming request.</param> /// <param name="Response">The outgoing response.</param> /// <param name="VerifyResult">A delegate to verify and filter results.</param> /// <param name="Timeout">A timeout for this operation.</param> /// <param name="DefaultResult">A default result in case of errors or a timeout.</param> public Task <T> WhenFirst <T>(DateTime ServerTimestamp, HTTPAPI OCPIAPI, OCPIRequest Request, OCPIResponse Response, Func <T, Boolean> VerifyResult, TimeSpan?Timeout = null, Func <TimeSpan, T> DefaultResult = null) { #region Data List <Task> _invocationList; Task WorkDone; Task <T> Result; DateTime StartTime = DateTime.UtcNow; Task TimeoutTask = null; #endregion lock (subscribers) { _invocationList = subscribers. Select(callback => callback(ServerTimestamp, OCPIAPI, Request, Response)). ToList(); if (Timeout.HasValue) { _invocationList.Add(TimeoutTask = Task.Run(() => System.Threading.Thread.Sleep(Timeout.Value))); } } do { try { WorkDone = Task.WhenAny(_invocationList); _invocationList.Remove(WorkDone); if (WorkDone != TimeoutTask) { Result = WorkDone as Task <T>; if (Result != null && !EqualityComparer <T> .Default.Equals(Result.Result, default(T)) && VerifyResult(Result.Result)) { return(Result); } } } catch (Exception e) { DebugX.LogT(e.Message); WorkDone = null; } }while (!(WorkDone == TimeoutTask || _invocationList.Count == 0)); return(Task.FromResult(DefaultResult(DateTime.UtcNow - StartTime))); }
/// <summary> /// Call all subscribers in parallel and wait for all to complete. /// </summary> /// <param name="ServerTimestamp">The timestamp of the event.</param> /// <param name="OCPIAPI">The sending OCPI/HTTP API.</param> /// <param name="Request">The incoming request.</param> public Task WhenAll(DateTime ServerTimestamp, HTTPAPI OCPIAPI, OCPIRequest Request) { Task[] _invocationList; lock (subscribers) { _invocationList = subscribers. Select(callback => callback(ServerTimestamp, OCPIAPI, Request)). ToArray(); } return(Task.WhenAll(_invocationList)); }
/// <summary> /// Call all subscribers sequentially. /// </summary> /// <param name="ServerTimestamp">The timestamp of the event.</param> /// <param name="OCPIAPI">The sending OCPI/HTTP API.</param> /// <param name="Request">The incoming request.</param> public async Task InvokeAsync(DateTime ServerTimestamp, HTTPAPI OCPIAPI, OCPIRequest Request) { OCPIRequestLogHandler[] _invocationList; lock (subscribers) { _invocationList = subscribers.ToArray(); } foreach (var callback in _invocationList) { await callback(ServerTimestamp, OCPIAPI, Request).ConfigureAwait(false); } }
/// <summary> /// Call all subscribers in parallel and wait for any to complete. /// </summary> /// <param name="ServerTimestamp">The timestamp of the event.</param> /// <param name="OCPIAPI">The sending OCPI/HTTP API.</param> /// <param name="Request">The incoming request.</param> /// <param name="Timeout">A timeout for this operation.</param> public Task WhenAny(DateTime ServerTimestamp, HTTPAPI OCPIAPI, OCPIRequest Request, TimeSpan?Timeout = null) { List <Task> _invocationList; lock (subscribers) { _invocationList = subscribers. Select(callback => callback(ServerTimestamp, OCPIAPI, Request)). ToList(); if (Timeout.HasValue) { _invocationList.Add(Task.Delay(Timeout.Value)); } } return(Task.WhenAny(_invocationList)); }
/// <summary> /// Add a method callback for the given URL template. /// </summary> /// <param name="CommonAPI">The OCPI Common API.</param> /// <param name="Hostname">The HTTP hostname.</param> /// <param name="HTTPMethod">The HTTP method.</param> /// <param name="URLTemplate">The URL template.</param> /// <param name="HTTPContentType">The HTTP content type.</param> /// <param name="URLAuthentication">Whether this method needs explicit uri authentication or not.</param> /// <param name="HTTPMethodAuthentication">Whether this method needs explicit HTTP method authentication or not.</param> /// <param name="ContentTypeAuthentication">Whether this method needs explicit HTTP content type authentication or not.</param> /// <param name="OCPIRequestLogger">A OCPI request logger.</param> /// <param name="OCPIResponseLogger">A OCPI response logger.</param> /// <param name="DefaultErrorHandler">The default error handler.</param> /// <param name="OCPIRequestHandler">The method to call.</param> public static void AddOCPIMethod(this CommonAPI CommonAPI, HTTPHostname Hostname, HTTPMethod HTTPMethod, HTTPPath URLTemplate, HTTPContentType HTTPContentType = null, HTTPAuthentication URLAuthentication = null, HTTPAuthentication HTTPMethodAuthentication = null, HTTPAuthentication ContentTypeAuthentication = null, OCPIRequestLogHandler OCPIRequestLogger = null, OCPIResponseLogHandler OCPIResponseLogger = null, HTTPDelegate DefaultErrorHandler = null, OCPIRequestDelegate OCPIRequestHandler = null, URLReplacement AllowReplacement = URLReplacement.Fail) { CommonAPI.HTTPServer. AddMethodCallback(Hostname, HTTPMethod, URLTemplate, HTTPContentType, URLAuthentication, HTTPMethodAuthentication, ContentTypeAuthentication, (timestamp, httpAPI, httpRequest) => OCPIRequestLogger?.Invoke(timestamp, null, HTTP.OCPIRequest.Parse(httpRequest, CommonAPI)), (timestamp, httpAPI, httpRequest, httpResponse) => OCPIResponseLogger?.Invoke(timestamp, null, httpRequest.SubprotocolRequest as OCPIRequest, (httpResponse.SubprotocolResponse as OCPIResponse) ?? new OCPIResponse(httpRequest.SubprotocolRequest as OCPIRequest, 2000, "OCPIResponse is null!", httpResponse.HTTPBodyAsUTF8String, httpResponse.Timestamp, httpResponse)), DefaultErrorHandler, async httpRequest => { try { // When no OCPIRequestLogger was used! if (httpRequest.SubprotocolRequest is null) { httpRequest.SubprotocolRequest = OCPIRequest.Parse(httpRequest, CommonAPI); } var OCPIResponseBuilder = await OCPIRequestHandler(httpRequest.SubprotocolRequest as OCPIRequest); var httpResponseBuilder = OCPIResponseBuilder.ToHTTPResponseBuilder(); httpResponseBuilder.SubprotocolResponse = new OCPIResponse(OCPIResponseBuilder.Request, OCPIResponseBuilder.StatusCode ?? 3000, OCPIResponseBuilder.StatusMessage, OCPIResponseBuilder.AdditionalInformation, OCPIResponseBuilder.Timestamp ?? DateTime.UtcNow, httpResponseBuilder.AsImmutable); return(httpResponseBuilder); } catch (Exception e) { return(new HTTPResponse.Builder(HTTPStatusCode.InternalServerError) { ContentType = HTTPContentType.JSON_UTF8, Content = new OCPIResponse <JObject>( JSONObject.Create( new JProperty("description", e.Message), new JProperty("stacktrace", e.StackTrace.Split(new String[] { Environment.NewLine }, StringSplitOptions.None).ToArray()), new JProperty("source", e.TargetSite.Module.Name), new JProperty("type", e.TargetSite.ReflectedType.Name) ), 2000, e.Message, null, DateTime.UtcNow, null, (httpRequest.SubprotocolRequest as OCPIRequest)?.RequestId, (httpRequest.SubprotocolRequest as OCPIRequest)?.CorrelationId ).ToJSON(json => json).ToUTF8Bytes(), Connection = "close" }); } }, AllowReplacement); }