private static void PublishWorkerResponse(ICoreClient client, InternalRequest internalRequest, string hostInstance) { if (internalRequest.Status == RequestStatusEnum.Undefined) { throw new ArgumentNullException("status"); } WorkerResponse response = new WorkerResponse() { RequestId = internalRequest.RequestId.ToString(), WorkerHostComputer = Environment.MachineName, WorkerHostInstance = hostInstance, Status = internalRequest.Status, FaultDetail = internalRequest.FaultDetail }; UserIdentity requesterId = null; if (internalRequest.ExternalRequest != null) { requesterId = internalRequest.ExternalRequest.RequesterId; } if ((requesterId == null) && (internalRequest.Cancellation != null)) { requesterId = internalRequest.Cancellation.RequesterId; } response.RequesterId = requesterId; if ((response.Status == RequestStatusEnum.Cancelled) && (internalRequest.Cancellation != null)) { response.CancelReason = internalRequest.Cancellation.CancelReason; } client.SaveObject <WorkerResponse>(response); }
public LaunchPackage(Reference <ICoreClient> clientRef, InternalRequest request) { _ClientRef = clientRef.Clone(); _Request = request; }
private void ProcessRequests(object notUsed) { try { // process rules and run handlers as required BasicServerState state = this.GetState(); if (state != BasicServerState.Running) { return; } // subscription is ready and callback flood has stopped List <InternalRequest> existingRequests = new List <InternalRequest>(); List <InternalRequest> enqueuedRequests = new List <InternalRequest>(); List <InternalRequest> cancelledRequests = new List <InternalRequest>(); var requestItems = _AssignedRequestsCache.Items; var cancellationItems = _CancellationsCache.Items; var responseItems = _WorkerResponseCache.Items; _InternalRequests.Locked((internalRequests) => { // - process responses foreach (ICoreItem item in responseItems) { try { WorkerResponse response = (WorkerResponse)item.Data; Guid requestId = Guid.Parse(response.RequestId); InternalRequest internalRequest; if (!internalRequests.TryGetValue(requestId, out internalRequest)) { internalRequest = new InternalRequest(requestId); } internalRequest.Status = response.Status; internalRequests[requestId] = internalRequest; } catch (Exception excp) { Logger.Log(excp); } } // - process requests foreach (ICoreItem item in requestItems) { try { AssignedWorkflowRequest request = (AssignedWorkflowRequest)item.Data; Guid requestId = Guid.Parse(request.RequestId); InternalRequest internalRequest; if (!internalRequests.TryGetValue(requestId, out internalRequest)) { internalRequest = new InternalRequest(requestId); } internalRequest.ExternalRequest = request; internalRequests[requestId] = internalRequest; } catch (Exception excp) { Logger.Log(excp); } } // - process cancellations foreach (ICoreItem item in cancellationItems) { try { CancellationRequest cancellation = (CancellationRequest)item.Data; Guid requestId = Guid.Parse(cancellation.RequestId); InternalRequest internalRequest; if (!internalRequests.TryGetValue(requestId, out internalRequest)) { internalRequest = new InternalRequest(requestId); } internalRequest.Cancellation = cancellation; internalRequests[requestId] = internalRequest; } catch (Exception excp) { Logger.Log(excp); } } // determine requests to be launched or cancelled foreach (InternalRequest internalRequest in internalRequests.Values) { if ((internalRequest.ExternalRequest != null) && ((internalRequest.Status == RequestStatusEnum.Undefined) || (internalRequest.Status == RequestStatusEnum.Enqueued))) { // find requests to launch if (internalRequest.Cancellation == null) { if (internalRequest.Status != RequestStatusEnum.Enqueued) { // new request internalRequest.Status = RequestStatusEnum.Enqueued; enqueuedRequests.Add(internalRequest); } existingRequests.Add(internalRequest); } else { // cancelled internalRequest.Status = RequestStatusEnum.Cancelled; cancelledRequests.Add(internalRequest); } } } }); // publish status for cancelled and enqueued requests foreach (InternalRequest request in cancelledRequests) { PublishWorkerResponse(_IntClient.Target, request, HostInstance); } // now find handlers to launch foreach (InternalRequest request in enqueuedRequests) { // publish enqueued status PublishWorkerResponse(_IntClient.Target, request, HostInstance); } foreach (InternalRequest request in existingRequests) { // launch if handler available int count = Interlocked.Decrement(ref _HandlersAvailable); if (count >= 0) { Interlocked.Increment(ref _AvailabilityChangeCount); Interlocked.Increment(ref _HandlersExecuting); // publish launched status request.Status = RequestStatusEnum.Launched; PublishWorkerResponse(_IntClient.Target, request, HostInstance); // launch ThreadPool.QueueUserWorkItem(Launch, new LaunchPackage(_IntClient, request)); } else { Interlocked.Increment(ref _HandlersAvailable); } } // publish availability (throttled) int changeCount = Interlocked.Exchange(ref _AvailabilityChangeCount, 0); if ((changeCount > 0) || ((DateTimeOffset.Now - _AvailabilityLastPublished) > TimeSpan.FromSeconds(5))) { _IntClient.Target.SaveObject <WorkerAvailability>(new WorkerAvailability() { WorkerHostComputer = Environment.MachineName, WorkerHostInstance = this.HostInstance, AvailableNodeCount = Interlocked.Add(ref _HandlersAvailable, 0) }); _AvailabilityLastPublished = DateTimeOffset.Now; } } catch (Exception e) { Logger.Log(e); } }