void cancel(Order order) { if (order != null) { //TODO enqueue order order = null; mode = WorkerMode.Idle; } }
/// <summary> /// Internal constructor. /// </summary> /// <param name="client">The parent client.</param> /// <param name="mode">Identifies whether the worker will process activities, workflows, or both.</param> /// <param name="workerId">The ID of the worker as tracked by the <b>cadence-proxy</b>.</param> /// <param name="domain">The Cadence domain where the worker is registered.</param> /// <param name="taskList">The Cadence task list.</param> internal Worker(CadenceClient client, WorkerMode mode, long workerId, string domain, string taskList) { this.Client = client; this.Mode = mode; this.WorkerId = workerId; this.Domain = domain; this.Tasklist = taskList; this.RefCount = 1; }
public void SetWorkerMode(WorkerMode mode) { var comboBoxPtr = this.GetChildWindow(1, "ComboBox"); if (comboBoxPtr == IntPtr.Zero) { this.OnWorkerErrorOccurred("An incompatible worker is running"); return; } WinAPIUtils.SetComboBoxSelectedIndex(comboBoxPtr, GetExternalWorkerModeIndex(mode)); }
private int GetExternalWorkerModeIndex(WorkerMode mode) { switch (mode) { case WorkerMode.Disabled: return(0); case WorkerMode.WorkWhenIdle: return(1); case WorkerMode.WorkProportional: return(3); case WorkerMode.WorkAlways: return(2); default: Debug.Assert(false, "Unsupported worker mode"); return(0); } }
/// <summary> /// Signals Cadence that the application is capable of executing workflows and/or activities for a specific /// domain and task list. /// </summary> /// <param name="taskList">Specifies the task list implemented by the worker. This must not be empty.</param> /// <param name="options">Optionally specifies additional worker options.</param> /// <param name="domain">Optionally overrides the default <see cref="CadenceClient"/> domain.</param> /// <returns>A <see cref="Worker"/> identifying the worker instance.</returns> /// <exception cref="ArgumentNullException">Thrown if <paramref name="taskList"/> is <c>null</c> or empty.</exception> /// <exception cref="InvalidOperationException"> /// Thrown when an attempt is made to recreate a worker with the /// same properties on a given client. See the note in the remarks. /// </exception> /// <remarks> /// <note> /// <see cref="CadenceClient"/> for more information on task lists. /// </note> /// <para> /// Your workflow application will need to call this method so that Cadence will know /// that it can schedule activities to run within the current process. You'll need /// to specify the target Cadence domain and task list. /// </para> /// <para> /// You may also specify an optional <see cref="WorkerOptions"/> parameter as well /// as customize the name used to register the activity, which defaults to the /// fully qualified name of the activity type. /// </para> /// <para> /// This method returns a <see cref="Worker"/> which implements <see cref="IDisposable"/>. /// It's a best practice to call <see cref="Dispose()"/> just before the a worker process /// terminates, but this is optional. Advanced worker implementation that need to change /// their configuration over time can also call <see cref="Dispose()"/> to stop workers /// for specific domains and task lists. /// </para> /// <note> /// The Cadence GOLANG client does not appear to support starting a worker with a given /// set of parameters, stopping that workflow, and then restarting another worker /// with the same parameters on the same client. This method detects this situation /// and throws an <see cref="InvalidOperationException"/> when a restart is attempted. /// </note> /// </remarks> public async Task <Worker> StartWorkerAsync(string taskList, WorkerOptions options = null, string domain = null) { await SyncContext.ClearAsync; Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(taskList), nameof(taskList), "Workers must be started with a non-empty workflow."); EnsureNotDisposed(); options = options ?? new WorkerOptions(); domain = ResolveDomain(domain); WorkerMode mode = options.Mode; Worker worker; try { using (await workerRegistrationMutex.AcquireAsync()) { // Ensure that we haven't already registered a worker for the // specified activity, domain, and task list. We'll just increment // the reference count for the existing worker and return it // in this case. // // I know that this is a linear search but the number of activity // registrations per service will generally be very small and // registrations will happen infrequently (typically just once // per service, when it starts). // $note(jefflill): // // If the worker exists but its RefCount==0, then we're going to // throw an exception because Cadence doesn't support recreating // a worker with the same parameters on the same client. worker = workers.Values.SingleOrDefault(wf => wf.Mode == mode && wf.Domain == domain && wf.Tasklist == taskList); if (worker != null) { if (worker.RefCount < 0) { throw new InvalidOperationException("A worker with these same parameters has already been started and stopped on this Cadence client. Cadence does not support recreating workers for a given client instance."); } Interlocked.Increment(ref worker.RefCount); return(worker); } options = options ?? new WorkerOptions(); var reply = (NewWorkerReply)(await CallProxyAsync( new NewWorkerRequest() { Domain = ResolveDomain(domain), TaskList = taskList, Options = options.ToInternal() })); reply.ThrowOnError(); worker = new Worker(this, mode, reply.WorkerId, domain, taskList); workers.Add(reply.WorkerId, worker); } } finally { switch (mode) { case WorkerMode.Activity: activityWorkerStarted = true; break; case WorkerMode.Workflow: workflowWorkerStarted = true; break; case WorkerMode.Both: activityWorkerStarted = true; workflowWorkerStarted = true; break; default: throw new NotImplementedException(); } } // Fetch the stub for each registered workflow and activity type so that // they'll be precompiled so compilation won't impact workflow and activity // performance including potentially intruducing enough delay to cause // decision tasks or activity heartbeats to fail (in very rare situations). // // Note that the compiled stubs are cached, so we don't need to worry // about compiling stubs for types more than once causing a problem. lock (registeredWorkflowTypes) { foreach (var workflowInterface in registeredWorkflowTypes) { // Workflows, we're going to compile both the external and child // versions of the stubs. StubManager.GetWorkflowStub(workflowInterface, isChild: false); StubManager.GetWorkflowStub(workflowInterface, isChild: true); } } lock (registeredActivityTypes) { foreach (var activityInterface in registeredActivityTypes) { StubManager.GetActivityStub(activityInterface); } } return(worker); }
private void SettingsPage_WorkerModeChanged(object sender, WorkerMode mode) { UpdateTrayIcon(); }
public void handle() { if (mode == WorkerMode.GoToProducer) { //TODO moveTo(); mode = WorkerMode.GoingToProducer; } if (mode == WorkerMode.GoingToProducer) { move(); if (next == null) { mode = WorkerMode = OrderRessources; } } else if (mode == WorkerMode.OrderRessources) { //TODO mode = WorkerMode.WaitForRessources; } else if (mode == WorkerMode.WaitForRessources) { //TODO } else if (mode == WorkerMode.ProduceProduct) { long productionReady = DateTime.Now.Ticks/TimeSpan.TicksPerMillisecond + order.recipe.time*order.number; mode = WorkerMode.ProducingProduct; } else if (mode == WorkerMode.ProducingProduct) { if (DateTime.Now.Ticks/TimeSpan.TicksPerMillisecond >= productionReady) { mode = WorkerMode.LoadProducts; } } else if (mode == WorkerMode.ImproveProducts) { //TODO } else if (mode == WorkerMode.ImproveingProducts) { //TODO } else if (mode == WorkerMode.LoadProducts) { //TODO mode = WorkerMode.DeliverProducts; } else if (mode == WorkerMode.DeliverProducts) { //TODO moveTo(); mode = WorkerMode.DeliveringProducts; } else if (mode == WorkerMode.DeliveringProducts) { move(); if (next == null) { mode = WorkerMode.UnloadProducts; } } else if (mode == WorkerMode.UnloadProducts) { //TODO mode = WorkerMode.Idle; order = null; priority = Priority.Idle; //TODO dequeue //TODO enqueue } else if (mode == WorkerMode.Build) { } else if (mode == WorkerMode.Idle) { } }
private void WorkerPage_WorkerModeChanged(object sender, WorkerMode mode) { ChangeWorkerMode((int)mode); }
public void handle() { if (mode == WorkerMode.GoToProducer) { //TODO moveTo(); mode = WorkerMode.GoingToProducer; } if (mode == WorkerMode.GoingToProducer) { move(); if (next == null) { mode = WorkerMode = OrderRessources; } } else if (mode == WorkerMode.OrderRessources) { //TODO mode = WorkerMode.WaitForRessources; } else if (mode == WorkerMode.WaitForRessources) { //TODO } else if (mode == WorkerMode.ProduceProduct) { long productionReady = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond + order.recipe.time * order.number; mode = WorkerMode.ProducingProduct; } else if (mode == WorkerMode.ProducingProduct) { if (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond >= productionReady) { mode = WorkerMode.LoadProducts; } } else if (mode == WorkerMode.ImproveProducts) { //TODO } else if (mode == WorkerMode.ImproveingProducts) { //TODO } else if (mode == WorkerMode.LoadProducts) { //TODO mode = WorkerMode.DeliverProducts; } else if (mode == WorkerMode.DeliverProducts) { //TODO moveTo(); mode = WorkerMode.DeliveringProducts; } else if (mode == WorkerMode.DeliveringProducts) { move(); if (next == null) { mode = WorkerMode.UnloadProducts; } } else if (mode == WorkerMode.UnloadProducts) { //TODO mode = WorkerMode.Idle; order = null; priority = Priority.Idle; //TODO dequeue //TODO enqueue } else if (mode == WorkerMode.Build) { } else if (mode == WorkerMode.Idle) { } }
/// <summary> /// Signals Cadence that the application is capable of executing activities for a specific /// domain and task list. /// </summary> /// <param name="taskList">Optionally specifies the target task list (defaults to <b>"default"</b>).</param> /// <param name="options">Optionally specifies additional worker options.</param> /// <param name="domain">Optionally overrides the default <see cref="CadenceClient"/> domain.</param> /// <returns>A <see cref="Worker"/> identifying the worker instance.</returns> /// <exception cref="InvalidOperationException"> /// Thrown when an attempt is made to recreate a worker with the /// same properties on a given client. See the note in the remarks. /// </exception> /// <remarks> /// <para> /// Your workflow application will need to call this method so that Cadence will know /// that it can schedule activities to run within the current process. You'll need /// to specify the target Cadence domain and task list. /// </para> /// <para> /// You may also specify an optional <see cref="WorkerOptions"/> parameter as well /// as customize the name used to register the activity, which defaults to the /// fully qualified name of the activity type. /// </para> /// <para> /// This method returns a <see cref="Worker"/> which implements <see cref="IDisposable"/>. /// It's a best practice to call <see cref="Dispose()"/> just before the a worker process /// terminates, but this is optional. Advanced worker implementation that need to change /// their configuration over time can also call <see cref="Dispose()"/> to stop workers /// for specific domains and task lists. /// </para> /// <note> /// The Cadence GOLANG client does not appear to support starting a worker with a given /// set of parameters, stopping that workflow, and then restarting another worker /// with the same parameters on the same client. This method detects this situation /// and throws an <see cref="InvalidOperationException"/> when these restart attempts /// are made. /// </note> /// </remarks> private async Task <Worker> StartWorkerAsync(string taskList = "default", WorkerOptions options = null, string domain = null) { Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(taskList)); options = options ?? new WorkerOptions(); WorkerMode mode = options.Mode; Worker worker; try { using (await workerRegistrationMutex.AcquireAsync()) { // Ensure that we haven't already registered a worker for the // specified activity, domain, and task list. We'll just increment // the reference count for the existing worker and return it // in this case. // // I know that this is a linear search but the number of activity // registrations per service will generally be very small and // registrations will happen infrequently (typically just once // per service, when it starts). // $note(jeff.lill): // // If the worker exists but its refcount==0, then we're going to // throw an exception because Cadence doesn't support recreating // a worker with the same parameters on the same client. worker = workers.Values.SingleOrDefault(wf => wf.Mode == mode && wf.Domain == domain && wf.Tasklist == taskList); if (worker != null) { if (worker.RefCount == 0) { throw new InvalidOperationException("A worker with these same parameters has already been started and stopped on this Cadence client. Cadence does not support recreating workers for a given client instance."); } Interlocked.Increment(ref worker.RefCount); return(worker); } options = options ?? new WorkerOptions(); var reply = (NewWorkerReply)(await CallProxyAsync( new NewWorkerRequest() { Domain = ResolveDomain(domain), TaskList = taskList, Options = options.ToInternal() })); reply.ThrowOnError(); worker = new Worker(this, mode, reply.WorkerId, domain, taskList); workers.Add(reply.WorkerId, worker); } } finally { switch (mode) { case WorkerMode.Activity: activityWorkerStarted = true; break; case WorkerMode.Workflow: workflowWorkerStarted = true; break; case WorkerMode.Both: activityWorkerStarted = true; workflowWorkerStarted = true; break; default: throw new NotImplementedException(); } } return(worker); }