Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Requeue to initial queue #502

Open
wants to merge 3 commits into
base: master
from

Conversation

@seertenedos

This comment has been minimized.

Copy link

commented Jan 28, 2016

Any idea when this fix will be merged in?

@gandarez

This comment has been minimized.

Copy link
Author

commented Jan 28, 2016

Still waiting priority

@odinserj

This comment has been minimized.

Copy link
Member

commented Jan 29, 2016

This is by design. The Queue property is related to the EnqueuedState, and not to background job itself. In Hangfire, background jobs don't know anything about queues, schedules, cron strings, etc. They only contain invocation data (type, method, arguments), have unique identifier and current state.

The current state determines the further processing logic, and may have an additional information, such as queue for enqueued jobs. Current state is volatile, and states are unrelated to each other. If you want to assign some parameter to a background job, you can use SetJobParameter and GetJobParameter methods of the JobStorageConnection class using job filters.

This distinction of properties between jobs and states allows Hangfire to be highly extensible, allowing to add more features as plugins, including new states, new processing rules and so on. The feature you are proposing may be implemented using the following job filter.

public class PreserveOriginalQueueAttribute : JobFilterAttribute, IApplyStateFilter
{
    public void OnStateApplied(ApplyStateContext context, IWriteOnlyTransaction transaction)
    {
        var enqueuedState = context.NewState as EnqueuedState;

        // Activating only when enqueueing a background job
        if (enqueuedState != null)
        {
            // Checking if an original queue is already set
            var originalQueue = JobHelper.FromJson<string>(context.Connection.GetJobParameter(
                context.BackgroundJob.Id,
                "OriginalQueue"));

            if (originalQueue != null)
            {
                // Override any other queue value that is currently set (by other filters, for example)
                enqueuedState.Queue = originalQueue;
            }
            else
            {
                // Queueing for the first time, we should set the original queue
                context.Connection.SetJobParameter(
                    context.BackgroundJob.Id,
                    "OriginalQueue",
                    JobHelper.ToJson(enqueuedState.Queue));    
            }
        }
    }

    public void OnStateUnapplied(ApplyStateContext context, IWriteOnlyTransaction transaction)
    {
    }
}

You can decorate a method using this filter, add this filter globally using UseFilter method (GlobalConfiguration.Configuration), or combine it with the QueueAttribute filter, it will work fine. I don't want to add as the default filter, because it requires additional storage round-trips. However, it should be documented as well, as an example.

@gandarez

This comment has been minimized.

Copy link
Author

commented Feb 1, 2016

@odinserj I followed your example and it seems not to be working.

image
image

@odinserj

This comment has been minimized.

Copy link
Member

commented Feb 9, 2016

@gandarez, how do you enqueue your background job, and how do you apply the filter? I see the OriginalQueue parameter is set to default, this means filter was plugged in, but it hasn't applied, or rewritten previous value for some reason.

@gandarez

This comment has been minimized.

Copy link
Author

commented Feb 12, 2016

@odinserj The job listed above is enqueded exactly the same way as recurring one. The difference is that I created a new class (inherited from recurring) that internally is called as persistent because I need to trigger through the Dashboard all the jobs non-recurring. So following this scenario I applied the filter you wrote:

.UseFilter(new PreserveOriginalQueueAttribute());

When I run the Sample project from Hangfire solution it goes like a charm but if I do it from my windows service as explained above it simply doesn't apply the filter.

Any idea?

@odinserj

This comment has been minimized.

Copy link
Member

commented May 23, 2016

Hi @gandarez, is the problem with PreserveOriginalQueueAttribute still relevant?

@gandarez

This comment has been minimized.

Copy link
Author

commented May 23, 2016

@odinserj I might test it again. I hope do it soon and tell you.

@gandarez

This comment has been minimized.

Copy link
Author

commented Jun 3, 2016

@odinserj It's not working when the recurring job has been triggered manually.

What I see debugging the code is that all recurring jobs come from "Scheduled" to "Enqueued" state nevertheless all triggered jobs starts on "Enqueued" and there's no State Machine at this point.

Triggered by recurring job scheduler
image

Triggered using recurring job manager
image

image

@gandarez

This comment has been minimized.

Copy link
Author

commented Jun 24, 2016

@odinserj help me!

@ZA1

This comment has been minimized.

Copy link

commented Aug 16, 2016

I needed this feature and the filter that @odinserj provided works. We have a separate service that runs the tasks and the dashboard is just a view into that database. What got me is that I did not add the filter to the Dashboard configuration so when re-queuing the jobs form the dashboard the job landed up in the default queue.

After I added the filter to the dashboard queue as well as the service configuration it worked like a charm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
4 participants
You can’t perform that action at this time.