towerofpower256 / davidmac.pro

My personal website
0 stars 1 forks source link

posts/2023-02-23-sn-custom-event-queue/ #23

Open utterances-bot opened 1 year ago

utterances-bot commented 1 year ago

Using custom ServiceNow event queues to solve race conditions

Lots of things all running at the same moment can cause timing issues when they all want to touch the same data. Here's a way you can avoid these issues easily and gracefully in ServiceNow using custom event queues and GlideEventManager.

https://davidmac.pro/posts/2023-02-23-sn-custom-event-queue/

tygroach commented 1 year ago

Love this David, thank you! Suggestion - it might be nice to add example code for the GlideEventManager("test_queue").process();

Maybe I missed it, but I'm guessing you need to register some callback function that implements "process"?

towerofpower256 commented 1 year ago

Love this David, thank you! Suggestion - it might be nice to add example code for the GlideEventManager("test_queue").process();

Maybe I missed it, but I'm guessing you need to register some callback function that implements "process"?

I'm glad you like it @tygroach! It was a cool revelation when I found it.

You don't get to see what happens behind .process(), it gets ServiceNow to handle the event as it would any other event. It'll trigger any related notifications, script actions for those events, and what-not related to those kinds of events. GlideEventManager just lets you decide when those events get processed, not how they get processed.

tygroach commented 1 year ago

Thanks David. Man...learn something new every day! I really like this. Thanks for the added explanation and for bringing this to light! Great job mate!

jimser commented 1 year ago

In the related ServiceNow article, the processor is created directly on the sys_trigger table. This makes it possible to set the System ID setting to "ACTIVE NODES". This would automatically create instances of the event processor per node. In your example, you create a scheduled job (sysauto_script) directly. The associated sys_trigger is then read-only and can no longer be changed and then only runs on one node? Is that a disadvantage from a performance point of view?

tygroach commented 1 year ago

Hey David...one more dumb question. So I'm going to try to use this in an Inbound Action (reply email handling). The reason - sometimes the person sending the reply to the email does not have the necessary SN roles to even read certain tables which need to be updated, so I was thinking of this blog-post. I'll just create an event to go against my custom queue and then process that event (run-as admin).

My question is...how do you access the record (gr in your example) that is passed as the 2nd parameter in the gs.eventQueue("test_event", gr, "", "", "a_totally_different_queue")? For that matter, how do you get access to event.param1 and event.param2 in our processing script?

https://docs.servicenow.com/bundle/utah-api-reference/page/script/useful-scripts/task/queues-create.html

towerofpower256 commented 1 year ago

In the related ServiceNow article, the processor is created directly on the sys_trigger table. This makes it possible to set the System ID setting to "ACTIVE NODES". This would automatically create instances of the event processor per node. In your example, you create a scheduled job (sysauto_script) directly. The associated sys_trigger is then read-only and can no longer be changed and then only runs on one node? Is that a disadvantage from a performance point of view?

Well spotted. Yes, running this processor would be consumed by a single node. That is it's advantage. If there is a very large backlog of events for a single queue and it's processed normally, the load would be spread evenly across every node, possibly consuming almost all resources on every node, which is bad.

However, if you restrict it to a single node, the performance impact is limited to a single node, and the other nodes are free to continue at a normal speed.

towerofpower256 commented 1 year ago

@tygroach I wouldn't say that you'd do that in the event queue processor class itself, it's just responsible for being the engine that the events go through.

The events themselves are still handled as usual. The events aren't aware of how they're being processed, just that they are being processed.

However, in your example, you could totally use an event to achieve what you're after, yes. It wouldn't have to be a custom event queue either. Unless you get obliterated with 5,000 emails in a single second, I don't think you'll need to use a custom queue for that.

But yea, create a new event registration, and a new event script action to run when that event gets triggered, and an inbound email action to trigger that event when certain email conditions are met.

https://docs.servicenow.com/en-US/bundle/utah-platform-administration/page/administer/platform-events/reference/r_ScriptActions.html

Within your script action there should be 2 objects available to you:

sauravpaira commented 1 year ago

David, is this going to work from a Scoped application. I am creating the scheduled job from scoped application and invoking the GlideEventManager, but I think GlideEventManager is not accessible from Scoped Application. Can you please confirm ? and do you suggest any alternatives from scoped application?

towerofpower256 commented 1 year ago

@sauravpaira good question.

Sadly, it doesn't look like you can. Here's the error message I get when I try to use it in a background script:

java.lang.SecurityException: GlideEventManager is not allowed in scoped applications:

If you really REALLY have to, you can create a scoped wrapper script include around GlideEventManager that you can access from scoped application, but you wouldn't be able to ship that with your scoped application & you'd need to ask your customers to create that wrapper script include manually.