HI, anybody got any ideas as to why a record create in an ActiveJob perform would be creating two records?
I simplified the code to only run the create function.
This happens when running the server, does not when running test.
I am using sqlite3, the in-process queuing system, rails 7.0.4.3.
The code runs fine in the console.
The log shows only 1 sql insert.
Are you using CanCanCan by any chance? I have had “double load” issues if I use its load_and_authorize_resource controller method AND initialize manually in the controller method by mistake.
Hi Walter, I’m using rufus-scheduler. I just use it to run a job every minute (should be real simple stuff!), but there are two instances created which don’t appear to be sharing a rails instance.
I don’t know the details of the rails startup logic and there doesn’t seem to be much documentation.
I’m considering creating a lock file so only one instance starts the job, but this is messy as I now have to make sure the file gets removed on shutdown.
I hope someone can give some clues on how this should be done.
If you have two instances processing the same job queue you’ll definitely see that happen without some kind of lock system in place. Are you processing via redis?
I’m not using redis, I just want a light weight job to be run every minute.
The ActiveJob seems to run without a problem. I just have to figure out how to stop two schedulers being started, which doubles up the number of jobs.
I’m not being blocked by this right now, so I’m giving this thread a few days hoping someone who is familiar with the rails startup process would kindly point me in the right direction.
Hi Nick, my setup is a bog standard rails app. I’m running it in development mode on my local computer ‘rails s’.
I get the impression rails forks a new process during initialization, and runs two instances.
I haven’t gone through the rails source yet so I don’t know exactly whats happening.
It could be Zeitwork for all I know at this point, so this might have nothing to do with rails itself.
I should try to disable Zeitwork and see if that solves the problem.
I will post if it works just in case someone else has the problem.
If ActiveJob works the way DelayedJob or Sidekiq does, then yes, it will start another Rails process just to handle the individual jobs. That’s why all of those asynchronous handlers are designed to share nothing. You don’t pass them an instance, you pass them the identification needed to find that instance on their own, for example. A job should be a recipe, with the first step being “find this record and instantiate it”, not a method that acts on a provided instance.
Hi Walter, I’m pretty sure ActiveJob is working properly and is doing what it is asked to do.
The problem is in the startup of the server and the initialization code , which is in the initializers directory, is being called twice which causes two timers to be started, and each of those timers generate 1 ActiveJob each.
Btw does anyone know how to change the title of the thread? It doesn’t really describe the real problem i’m having.
Oh. Okay. So the issue really is that task you want to perform is being scheduled twice, and isn’t somehow idempotent. Would that give you any idea how to solve this? Does it need to be scheduled by app start, or is there another event or timing mechanism you could use instead? Is there a way to refactor the task so that it will end early if it notices that it’s redundant?
Ideally, the ActiveJob tasks should be considered an interface to a separate application from the regular “front end” application that users experience, even if they are running the same codebase. They share a single database (conceptually, anyway) but they have nothing else in common. It is one of the things you have to work through when deploying such an app, that you have to ensure you restart both the Web server and the job runner daemon in order to ensure that they both have the “same” code to work from. If you don’t, it is possible for the two running applications to be entirely different from one another. That can be a source of bugs as well.
I really think that the issue you are facing is orthogonal to this. Look again at your task, and see how you can ensure that no matter how many times it is called, it only changes things once.