// can start if none of its dependencies are running or about to run private bool CanStart(RFWorkQueueItem i) { if (i.Item is RFGraphProcessInstruction) { var gpi = i.Item as RFGraphProcessInstruction; if (_processDependencies.ContainsKey(gpi.ProcessName)) { var depends = _processDependencies[gpi.ProcessName]; return(!_inProgress.Select(p => p.Item as RFProcessInstruction).Any(p => p != null && depends.Contains(p.ProcessName)) && !_readyQueue.Select(p => p.Item as RFProcessInstruction).Any(p => p != null && depends.Contains(p.ProcessName))); } } else if (i.Item is RFProcessInstruction) { // queue up identical instructions var pi = i.Item as RFProcessInstruction; var existingForSameProcess = _inProgress.Select(p => p.Item as RFProcessInstruction).Where(p => p != null && p.ProcessName == pi.ProcessName) .Union(_readyQueue.Select(p => p.Item as RFProcessInstruction).Where(p => p != null && p.ProcessName == pi.ProcessName)); if (existingForSameProcess.Any()) { if (_exclusiveProcesses.Contains(pi.ProcessName)) { // cannot run concurrently - queue return(false); } return(!existingForSameProcess.Any(e => RFEngineProcessorParam.Equals(e.ExtractParam(), pi.ExtractParam()))); // catalog update on same key events will be queued } } return(true); }
public static bool Equals(RFEngineProcessorParam l, RFEngineProcessorParam r) { if (l == null && r == null) { return(true); } else if (l != null && r != null) { return(l.Equals(r)); } return(false); }
public void QueueItem(RFWorkQueueItem i) { if (i.Item == null) { throw new RFSystemException(this, "Invalid empty work item received."); } Monitor.Enter(_sync); // ignore if already running or queued (timers) if (i.Item is RFProcessInstruction && (_inProgress.Any() || _readyQueue.Any())) { if (i.Item is RFGraphProcessInstruction) { // if one processor subscribes to multiple outputs of another processor duplicate // instruction can happen var gpi = i.Item as RFGraphProcessInstruction; var running = _inProgress.Where(p => p.Item is RFGraphProcessInstruction).Select(p => p.Item as RFGraphProcessInstruction).ToList(); if (running.Any(r => r.Instance.Equals(gpi.Instance) && r.ProcessName == gpi.ProcessName)) { RFStatic.Log.Debug(this, "Ignoring instruction {0} for as we have one running already", gpi); return; // ignore already in progress } var ready = _readyQueue.Where(p => p.Item is RFGraphProcessInstruction).Select(p => p.Item as RFGraphProcessInstruction).ToList(); if (ready.Any(r => r.Instance.Equals(gpi.Instance) && r.ProcessName == gpi.ProcessName)) { RFStatic.Log.Debug(this, "Ignoring instruction {0} for as we have one ready already", gpi); return; // ignore already ready } } // not sure this was used - probably not since this throws away an instruction rather than delays it /* * else * { * var pi = i.Item as RFProcessInstruction; * if (pi.Event is RFIntervalEvent) // allow concurrent processing of multiple files or external triggers but not timers * { * if (_inProgress.Any()) * { * var inProgress = _inProgress.Where(q => q.Item is RFProcessInstruction).Select(q => q.Item as RFProcessInstruction); * if (inProgress.Any(q => q.ProcessName == pi.ProcessName)) * { * return; // ignore already in progress - for example FTP taking longer than timed trigger * } * } * * if (_readyQueue.Any()) * { * var queued = _readyQueue.Where(q => q.Item is RFProcessInstruction).Select(q => q.Item as RFProcessInstruction); * if (queued.Any(q => q.ProcessName == pi.ProcessName)) * { * return; // ignore already same process queued * } * } * } * }*/ } if (i.Item is RFGraphProcessInstruction) { var gpi = i.Item as RFGraphProcessInstruction; if (gpi.Instance != null && gpi.Instance.ValueDate.HasValue) { long datePart = (gpi.Instance.ValueDate.Value.ToYMD() - (long)20000000) * 1000000; if (_processWeights.ContainsKey(gpi.ProcessName)) { var weight = _processWeights[gpi.ProcessName]; var queueKey = datePart + weight; if (_pendingInstructions.ContainsKey(queueKey)) { var potentialDupes = _pendingInstructions[queueKey].Select(d => d.Item as RFGraphProcessInstruction); // ignore duplicate if (potentialDupes.Any(qi => qi.ProcessName.Equals(gpi.ProcessName) && qi.Instance.Equals(gpi.Instance))) { RFStatic.Log.Debug(this, "Ignoring instruction {0} for as we have one in the queue already", gpi); Monitor.Exit(_sync); return; } } else { _pendingInstructions.Add(queueKey, new List <RFWorkQueueItem>()); } _pendingInstructions[queueKey].Add(i); _dispatchStore.Queued(i, queueKey); } else { RFStatic.Log.Info(this, "Assuming zero weighted for unweighted graph instruction {0}/{1}", gpi.ProcessName, gpi.Instance.ToString()); if (!_pendingInstructions.ContainsKey(datePart)) { _pendingInstructions.Add(datePart, new List <RFWorkQueueItem>()); } _pendingInstructions[datePart].Add(i); _dispatchStore.Queued(i, datePart); } } else { RFStatic.Log.Warning(this, "Received graph instruction for process {0} without instance date.", gpi.ProcessName); if (!_pendingInstructions.ContainsKey(0)) { _pendingInstructions.Add(0, new List <RFWorkQueueItem>()); } _pendingInstructions[0].Add(i); // no instance date _dispatchStore.Queued(i, 0); } RefreshReadyQueue(); } else if (i.Item is RFProcessInstruction) { var pi = i.Item as RFProcessInstruction; if (!_pendingInstructions.ContainsKey(0)) { _pendingInstructions.Add(0, new List <RFWorkQueueItem>()); } // if we already have an identical pending instruction, we ignore (meaning we'll // still queue if there's an identical one already *in progress*) the logic here is // that if there's been multiple instances of the same event, we only process once var potentialDupes = _pendingInstructions[0].Select(p => p.Item as RFProcessInstruction).Where(p => p != null && p.ProcessName == pi.ProcessName); if (!potentialDupes.Any(d => RFEngineProcessorParam.Equals(d?.ExtractParam(), pi?.ExtractParam()))) { _pendingInstructions[0].Add(i); // no instance date _dispatchStore.Queued(i, 0); RefreshReadyQueue(); } /*else * { * RFStatic.Log.Debug(this, "Ignoring already pending RFProcessInstruction {0}", pi); * }*/ } else { _readyQueue.Add(i); // straight to readyqueue _dispatchStore.Queued(i, 0); Monitor.PulseAll(_sync); } RefreshInstructionCount(); Monitor.Exit(_sync); }