What Domino Makes Trivial Number Two: Synchronous / Asynchronous Processing

Home » What Domino Makes Trivial Number Two: Synchronous / Asynchronous Processing

Another topic that becomes key when moving beyond Domino is synchronous and asynchronous processing. But it's probably something most Domino developers haven't come across.

LotusScript and standard Domino Java are single-threaded. That means your code starts at line 1, runs line 1, then line 2, then line 3. If line 4 is a function / method, it stops processing the main code, jumps into the function / method, runs line 1, line 2 etc to the end point. Then it jumps back to the main code and continues to run lines 5, 6, 7 etc. If it calls NotesAgent.run, the main code stops while the agent runs, and then restarts once the agent finishes, all in a single thread. The Notes Client is tied up while the code runs - it too is single-threaded.

Notes Client does provide a function for multi-threaded processing, an agent that is set to run in a background client thread. You can't use NotesUI classes - because it's running in a background thread, not prompting for user activity. But it allows code to run while other things are happening in Notes Client. Of course you need to be aware of potential impacts, depending on what your agent is doing.

Most developers have also done a "poor man's threaded processing". You may have set a flag on a document or created a "processing document" that a scheduled agent then picks up and processes. That agent is run by the Agent Manager, it's own thread - or rather multiple threads, since you can have multiple agent managers. If memory serves me correct, though, it's not full multi-threaded processing - it will only run one agent from an NSF at a time. This is "poor man's threaded processing" because there's no direct communication between the threads. The UI process doesn't kick off the scheduled agent, and the UI process doesn't wait for the scheduled process to finish.

HTTP is of course multi-threaded, like the Agent Manager. But the threads are totally independent. This is why developers have to handle a button being clicked twice by a user in a web application, causing double-processing. In XPages, that's typically done by using Fredrik Norling's Standy Dialog Control. And to be brutally honest, if you're not, you should.

But XPages code too is synchronous, even calls to agents wait for the agent to complete before running the next line. That's not because XPages code can't be asynchronous. XPages just hides that complexity and removes the choice from you. UPDATE: Thanks Sven Hasselbach (as ever) for pointing out XPagesExecutorService for running background threads in XPages. Here are some details: http://hasselba.ch/blog/?p=2180.

There was an OpenNTF project called Threads and Jobs. Probably not many are using it. A different approach to asynchronous processing was provided in ODA - XOTS. This is full asynchronous processing, comprising two parts. The first comes with Java - Runnables and Callables - but is extended to provide access to Domino and the XPages runtime via the various Tasklet classes in XOTS. The second is built in ODA, a manager to manage the threads, manage how many are available, run them, quit them, tell you which threads are running which chunks of asynchronous code, the tasklets. The tasklets that extend classes with "Runnable" in the name are kicked off unattended. Unlike synchronous code, if line 7 triggers a XOTS tasklet, that code is kicked off but at the same time lines 8 onwards in your main code continue to run. The XOTS tasklets that extend classes with "Callable" in the name are the really powerful ones. This is typically done if you want to run the same code with different parameters. You build up a collection of Callables with your parameters, then kick them off, and they run in parallel, using as many of those XOTS threads as they can. Your main code listens for them to complete and processes the results. Because it's asynchronous processing, tasklet 3 may finish before tasklet 1 or 2, you need to understand and handle that.

I won't mention DOTS here, but it's tangentially relevant to XPages and I'll come back to it.

Of course with Vaadin, because it's Java, you can run asynchronous code in Threads, see https://vaadin.com/blog/community-answer-processing-a-file-in-a-background-thread.

JavaScript, though, is single-threaded. And this is where JavaScript developers have had to understand and solve the problem, particularly where JavaScript running as a server in Node.js, for example, is concerned.

It's something being addressed currently in Node-RED in preparation for the 1.0 release. And I'd do a poor job trying to paraphrase Nick O'Leary's blog post, so I'd recommend you read it, even if you don't use Node-RED. It eloquently explains the challenge, the change in processing, and the Node.js Event Loop. If you're moving into Node.js-based JavaScript development, you'll need to understand this.

Vert.x has a similar concept, the Event Bus. Again, it's worth reading to understand the challenge of synchronous / asynchronous processing. The event bus handles receiving messages from chunks of code and passing it off to handlers to process them. But obviously this adds complexity in processing, e.g. handling messages that fail.

At the root of all this, in standard JavaScript, is a concept that JavaScript calls Promises and the use of Async and Await. This is in many ways similar to Callables in Java. There are plenty of articles about this on the internet, because it's a critical concept of JavaScript programming, so I won't link to one.

But a key concept that the Vert.x Event Bus mentions is the publish/subscribe message pattern. This is particularly relevant to Notes developers now, because this is what's being made more available in V11 and what every developer and admin should get familiar with, to optimise their experiences. Some advanced developers may already be aware of it, that Domino has an underlying publish/subscribe message pattern at the most fundamental layer. DOTS users may have used the DOTS message queue and I demonstrated using it from ODA at IBM Think a few years ago to send a notification within milliseconds of a document being saved and to register unauthorised tampering with a document to the server console. With V11 those messages can be published to some standard message queues, which can allow code to be kicked off if it subscribes to those messages. I'm sure we'll see more and it's one of the aspects I've been very interested in.

Think, for example, of all the places you code notification logic and business logic synchronously in your action buttons. It sends an email or posts a notification. But you code it every time, and if you want to notify in a different way to using emails, well...you get the picture. If those notifications were handled asynchronously by a pub/sub process, at server level - or even wider - then you start to revolutionise your applications. Archiving? Flag the document, listen for it in your pub/sub handler, and archive it _immediately_ rather than in a scheduled overnight process.

Obviously this isn't a full event management system likeVert.x's Event Bus or Node.js's Event Loop. Domino wasn't designed that way and it's never really become a requirement. The NSF has typically been a container for everything, with no expectation of design standards. Only in edge cases has code been developed at server-level or beyond, modular outside the NSF where the UI and bulk of business logic resides. There's no expectation that it will become this and no evidence that customers want that. It's designed to expose what's been there for a while for use beyond Domino, as an integration point for non-traditional applications. Obviously it's also key for web sockets functionality outside of the traditional Domino HTTP server, and it may well be used for that.

Yes, the Agent Manager will be there for a long time yet, but this could revolutionise the way applications are architected and built - if developers understand synchronous and asynchronous processing and embrace it.

7 thoughts on “What Domino Makes Trivial Number Two: Synchronous / Asynchronous Processing”

      1. Sure.

        1. Long running jobs
        Every long running job which would otherwise run in a timeout for the HTTP request has a benefit. In one application, I had to generate a complex Excelsheet, and the generation took about 2-5 mins (don’t ask!).
        The user clicks the button, and every 30 seconds a simple partial refresh checks if the sheet is there.

        2. Background processing
        In one of my applications, the user clicks on “Send Mails”. Now, a very complicated mail generation process starts, and this is done in background. UI is not blocked, and the users can directly continue with their work.

        3. Automatically Queuing of processes with high CPU / memory usage
        The jobs are processed automatically in a queue. I had problems with Apache POI and memory consumption if multiple users are doing what described in (1). By using the internal ThreadPool of the Executor Service, a limitation of the required resources is automatically given.

        4. Running in user context
        Instead of running a background agent and wait to the next run, the job is directly executed. An application which needed to update a lot of documents / views in different databases can do this in the background. Because of the SessionCloner, the code is running in users context, reader fields are considered.

        5. And last but not least: Because it is cool 😉

  1. Paul,
    This is a great article. Mixing synchronous and asynchronous events is challenging. On the front end promises help but only up to a point. It becomes almost an art at one point to handle things. I wish HCL include Web socket support in the Domino core.

    1. Hmm, seems my next post needs to be on the complexities of web sockets. Enabling it makes things easy if you’re managing it in your front-end application. But when there’s state management…here be dragons! Imagine the impact on the view state bean in XPages of a push changing the state of the view behind. And that’s without considering the impact on a partial refresh to update rows in a repeat with a push that’s occurred since the initial page load. I can’t speak on the technical issues around a web sockets piece in Domino HTTP, there may be limitations there too.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top