8.0: Event listener issues using alternate entry point

If I have a custom event listener whose module only defines the GetDeadlineEventListenerWithJobs entry point, it seems that no client applications can load it:

Events plugin 'LumaEvents' could not be loaded from the repository because: An error occurred in function "GetDeadlineEventListener" the event plugin script file "/luma/assets/production/deadline/repo-mel-8/custom/events/LumaEvents/LumaEvents.py": AttributeError : 'module' object has no attribute 'GetDeadlineEventListener' (Deadline.Events.DeadlineEventPluginException)

Event error:

2016-10-27 17:25:38: An error occurred in the "OnSlaveStartingJob" function in events plugin 'LumaEvents': An error occurred in function "OnSlaveStartingJob" the event plugin script file "/luma/assets/production/deadline/repo-mel-8/custom/events/LumaEvents/LumaEvents.py": Object reference not set to an instance of an object (Deadline.Events.DeadlineEventPluginException) 2016-10-27 17:25:38: at Deadline.Events.DeadlineEventPlugin.a (System.String A_0, System.Exception A_1) <0x41815430 + 0x00133> in <filename unknown>:0 2016-10-27 17:25:38: at Deadline.Events.DeadlineEventPlugin.OnSlaveStartingJob (System.String slaveName, Deadline.Jobs.Job job) <0x418291c0 + 0x0010f> in <filename unknown>:0 2016-10-27 17:25:38: at Deadline.Events.DeadlineEventManager.OnSlaveStartingJob (System.String slaveName, Deadline.Jobs.Job job, Deadline.Controllers.DataController dataController) <0x418286e0 + 0x00463> in <filename unknown>:0 2016-10-27 17:25:38: ---------- Inner Stack Trace (System.NullReferenceException) ---------- 2016-10-27 17:25:38: at Deadline.Events.DeadlineEventPlugin.OnSlaveStartingJob (System.String slaveName, Deadline.Jobs.Job job) <0x418291c0 + 0x00037> in <filename unknown>:0

I’ve stripped the listener code down to be about as compact as possible, while still showing signs of life:

[code]from Deadline.Events import *

class LumaEventListener(DeadlineEventListener):
def init(self):
self.OnJobStartedCallback += self.jobStarted
self.OnJobFinishedCallback += self.jobFinished
self.OnJobFailedCallback += self.jobFinished
self.OnSlaveStartedCallback += self.slaveStarted

def jobStarted(self, job):
    self.LogInfo('-- Job Started Event -- ')

def jobFinished(self, job):
    self.LogInfo('-- Job Finished Event -- ')

def slaveStarted(self, slave):
    self.LogInfo('-- Slave Started Event --')

def doCleanup(self):
    del self.OnJobStartedCallback
    del self.OnJobFinishedCallback
    del self.OnJobFailedCallback
    del self.OnSlaveStartedCallback

def GetDeadlineEventListenerWithJobs(jobs):
return LumaEventListener()

def CleanupDeadlineEventListener(listener):
listener.doCleanup()[/code]

If I define GetDeadlineEventListener and just have it call GetDeadlineEventListenerWithJobs, things seem to work.

Hey Nathan,

It turns out the “GetDeadlineEventListenerWithJobs” entry point was removed by design for 8.0, and we failed to update the documentation accordingly. In 8.0, we introduced sandboxing for application and event plugins to keep them running in a clean environment that was separate from the main Deadline application. For events, an additional change was to keep them loaded in memory, instead of loading them every time an event triggers. Now, we only reload them if an event file or setting changes, which reduces a lot of overhead for event triggers.

The side effect of this is that Events no longer have any job context when they’re initially loaded (because they’re loaded when the Deadline application starts), so having a “GetDeadlineEventListenerWithJobs” entry point doesn’t really make sense anymore.

Is this a problem for your event plugin? Or are you able to use the “GetDeadlineEventListener” entry point instead?

Thanks!
Ryan

Ah OK, that’s good to know. It’s no problem for me to switch to the alternate entry point, but I was thoroughly confused for a while.

Just out of curiosity, does that mean that a single instance of the event listener is now kept alive the entire time the client application is open? If so, that seems like it could have some adverse implications if the listener class needs to create and delete state.

It’s not guaranteed that they’ll stay loaded since they’re running in the “deadlinesandbox” process. I believe that any Sandbox can periodically be unloaded and reloaded, and we do that cycle on purpose for the render scripts to clean up things like environment state (os.environ should finally do what folks expect).

So, I don’t think you can rely on state being left around, but there’s a best-effort there. Jon knows the system through and through, so if you do hit some weird state circumstances I can do a deep dive with him to refresh myself.

Sorry, I think maybe I wasn’t clear. I’m interested in state not being kept around.