I'm running into some really strange problems with Horizon jobs, which seem to have access to models they've never loaded.
My application registers a singleton in the Service Container when it boots: CompanyService is a singleton that performs various tasks on a single contextual Company model. I specifically need CompanyService to be a singleton, as it is very resource-intensive to set up.
A typical queued job might loop through a group of models from e.g. Company::all(). Inside the loop, it calls CompanyService::setContext($company) — this sets a property on the CompanyService class to the $company model. Throughout the rest of the CompanyService class, all actions take place on the contextual model it's been assigned to work on.
I've noticed some jobs seem to be changing Company models they couldn't possibly have loaded. My hunch is that Horizon is persisting the same instance of the singleton between jobs. I scoured through the docs, and found this note:
"any static state created or modified by your application will not be automatically reset between jobs"
I'm being careful to apply the context before each action is performed within a job. But I'm wondering if there's a race-condition going on — if one job calls a long-running action on CompanyService, another simultaneous job could have changed the contextual Company to complete its own tasks — and the first job's contextual Company gets switched-out, directly underneath it?
If that's the case, how can I work around this? Is there a way to detect when application code is being run within a queue worker process?
I really hope that makes sense... I was up until 2am last night trying to figure this out and my brain feels like fudge :(