Grails-Plugin-Consortium / grails-jesque

1 stars 5 forks source link

Support Job with named vars., not just unnamed args. #18

Open edwardotis opened 7 years ago

edwardotis commented 7 years ago

Jesque supports Jobs with named arguments, 'vars', in addition to 'args'. @see Job.java

The grails JesqueService doesn't support this explicitly, but I can make my own Job instance to properly pass the named vars.


 Job newJob = new Job(MyBackgroundJob.simpleName, ["myFirstArgName":123, "mySecondArgName":"some value"])
jesqueService.enqueue(Constants.JESQUE_QUEUE_NAME, newJob)

The problem is in the grails GrailsWorkerImpl execute method. It is only looks for the Job.args, not Job.vars.

    protected void execute(final Job job, final String curQueue, final Object instance, final Object[] args) {
        this.jedis.set(key(WORKER, this.name), statusMsg(curQueue, job))
        try {
            log.info "Running perform on instance ${job.className}"
            final Object result
            this.listenerDelegate.fireEvent(JOB_EXECUTE, this, curQueue, job, instance, null, null)
            result = instance.perform(*args)
            success(job, instance, result, curQueue)
        } finally {
            this.jedis.del(key(WORKER, this.name))
        }
    }

    protected Object execute(final Job job, final String curQueue, final Object instance) throws Exception {
        log.info "Executing jog ${job.className}"
        if (instance instanceof WorkerAware) {
            ((WorkerAware) instance).setWorker(this);
        }
        return execute(job, curQueue, instance, job.args)
    }

Whereas the Java version is more convoluted, but when they do execute, it handles both args and vars in JesqueUtils.java, ReflectionUtils.java

    /**
     * Materializes a job by assuming the {@link Job#getClassName()} is a
     * fully-qualified Java type.
     *
     * @param job
     *            the job to materialize
     * @return the materialized job
     * @throws ClassNotFoundException
     *             if the class could not be found
     * @throws Exception
     *             if there was an exception creating the object
     */
    public static Object materializeJob(final Job job) throws ClassNotFoundException, Exception {
        final Class<?> clazz = ReflectionUtils.forName(job.getClassName());
        // A bit redundant since we check when the job type is added...
        if (!Runnable.class.isAssignableFrom(clazz) && !Callable.class.isAssignableFrom(clazz)) {
            throw new ClassCastException("jobs must be a Runnable or a Callable: " + clazz.getName() + " - " + job);
        }
        **return ReflectionUtils.createObject(clazz, job.getArgs(), job.getVars());**
    }
bp-FLN commented 5 years ago

I just verified that names vars are actually working (i think this has been fixed in #28) But as you said: you need to create your own job for that.

Actually i don't really see a use-case for this, as you can already inject services into jobs.