3

I created 2 agents, one made of Java and another made of Lotusscript. The java agent is scheduled to run every 5 minutes, while the lotusscript agent is scheduled to run every 15 minutes. Therefor there will come a time that they will simultaneously run. When that happens, the java agent must pause/wait until the lotusscript agent finished. I tried to simulate locking using Profile DOcuments and Environment Variables but to no avail. Is there a way that I can simulate locking between this two different agents? Please help. Thanks a lot!

Edit: I forgot to say that the 2 agents resides in TWO DIFFERENT databases, to complicate things more :(

John Bautista
  • 1,480
  • 3
  • 29
  • 60

4 Answers4

6

Why not writing a third Agent (maybe in an extra Database), which runs periodically every five Minutes, which starts the other two Agents:

  1. The Lotus Script Agent every time
  2. The Java Agent every third run

... then you are also in control of the run order, without any complicated lock mechanisms.

spookycoder
  • 1,053
  • 9
  • 14
  • Actually, this is a really good answer! I'll check this if I can make this work! Thanks. – John Bautista Sep 08 '11 at 00:47
  • 2
    I have seen this approach used, and it's ok in relatively simple situations, small scale is ok. But I have seen this approach crash servers to. It's primary risk is when an agent calls other agents it is no longer under the control of the server's settings for agents. The server has throttle settings to stop an agent from consuming 100% cpu. Agents called from other agents can do what they like. Also you will have no indication of what called the sub agent in the Notes log. So it carries risks. – angryITguy Sep 10 '11 at 05:30
  • 1
    You could also consider getting the 5 minute agent to call the Java agent every 3rd time (or perhaps by inspecting the clock and NotesAgent.LastRun). – Jon McAuliffe Sep 12 '11 at 22:35
4

This is a near foolproof way I have found that works for controlling the execution order of independent agents. I use a real notes document as a psuedo-lock document.

The way I have done this before is to keep a Notes document that represents a "lock". Don't use a database profile document as it's prone to replication/save conflict issues and you can't view it in a view.

The "lock" document can have a flag on it which tells the java agent whether it is allowed to run now. The java agent simply has code in it similar to this

Session s = NotesFactory.createSession();
Database db = s.getDatabase("This Server", "This database");
View vw = db.getView("(lockView)");
Document docControl = vw.getFirstDocument();
String sRunStatus = docControl.getItemValueString("runStatus");
boolean bContinue = false;
if (sRunStatus =="Go"){
    bContinue = true;
}
if(bContinue){
    //do agent code here....

    // reset the status to "wait". The lotusscript agent should then set it to "Go"
    // the other agent will execute on "wait" and then update the status to "Go" on 
    // completion to prevent simulatenous execution. Can also use different state names
    // instead of go/wait, like run0, run1, run2 etc
    docControl.replaceItemValue("runStatus", "wait");
    docControl.save(true);
}

Note that you use the agents to set "Go"/"wait" values in the "runStatus" field on a control document. You only need 1 document so you then only need to get the first document out of the view.

The equivalent logic should be even simpler to add in the LotusScript agent as well. The only downside I can find is that the java agent may not execute the code because the control document is not yet set to "go" and the "IF" test fails without running the logic, so it's not a pause as such, but prevents the Java agent from executing out of it's desired order with the lotusscript agent. But it would then fire on the next scheduled instance if the LotusScript agent has released it.

You can also extend this idea to manage a suite of agents and even chain multiple agents as well by using specific values like "RunAgent1", "RunAgent2", another benefit is that you can also capture execution start times, errors as well, or anything you require....

angryITguy
  • 9,332
  • 8
  • 54
  • 82
  • 2
    If you don't use this together with the Document Locking functionality of Notes/Domino, you are not going to be happy. What happens, if both Agent run "at the same time", read the "runStatus", see the "Go" and both run, after updating the document (probably creating a conflict document)? If you impelement a semaphore like this, you need document locking, as Jasper already pointed out. – leyrer Sep 07 '11 at 07:26
  • Can't happen. If you read the logic I have written more carefully, you will see that using a specific status for each agent to run on, will only permit that specific agent to run. I did not say that both agents execute on "Go" as you're implying. So, if "agentA" executes on "Go", and the "agentB" executes on "Wait", then only 1 agent will actually execute the required business logic, even if both execute simulataneously. I have updated the answer to be more explicit about the point you have raised. I would appreciate it if you revise your downvote on that basis. – angryITguy Sep 07 '11 at 07:38
  • 1
    Is this really a wait? It looks more like a cancel, and try next time. I would try to use a Thread.sleep() to make it wait for x seconds and then try again. – Jasper Duizendstra Sep 07 '11 at 08:28
  • I modified the code below (actually prior to your answer I did implement something similar to that, using profile documents). Instead of a simple continue event, I did an infinite loop that waits until the value in the lock document change. I know that in Java, data are pass by value, therefore what I did is to get the document again and again in the while's condition, just to make sure that the new document is passed. But still, the changes in the lock document doesn't appear when the 2 agents are simultaneously run. – John Bautista Sep 07 '11 at 10:38
  • @Jairo, you should not have an infinite loop this will block a queue on the agent manager and if you only have one queue, you will prevent agents from executing until the timeout limit for agents is reached. This also stresses out the server to it's maximum CPU limit for agents on the server. The default I believe is set to 70%. So don't do an infinite loop. If the frequency is critical, you can launch the java agent from the LS agent. It also has some risks, but would be much better than an infinite loop.There are still other approaches, but this would start to re-code your agents. – angryITguy Sep 07 '11 at 11:36
  • @Jasper. Thread.Sleep is almost as inappropriate as an infinite loop. Blocking the agent manager queue will impact the running of other agents on the server. And I think you would still need to periodically wakeup to check if the agent should continue. Again the risk is that the agent will timeout and block other agents at any time. Although Jairo asks for one agent to "Wait" what he is really asking is to manage the execution order of agents. – angryITguy Sep 07 '11 at 11:42
  • I believe trying to control the agent flow relative to each other is usually a bad idea anyway. In this case the documents are created every 5 minutes and fetched every 15. It is possible that the creation agent blocks the fetching agent, hence the sleep instead the try again later. If it keeps failing at every wake-up, the fetching agent runs to long and that would be a problem on its own. Most probably the solution is somewhere else, instead of deleting documents, updating them. – Jasper Duizendstra Sep 07 '11 at 12:19
  • I agree the design as described is not the best situation. But I can appreciate how these things "evolve" over time. Despite the shortcomings, it's a good question though, because Domino developers are faced with agent scheduling issues and I have found this approach works in most cases. – angryITguy Sep 07 '11 at 13:45
1

Enabling document locking in the database could work. If you can enable document locking in the database itself you can have the agents lock a specific document and check if the document is locked before/during it runs the code.

If enabling document locking in that database is not an option you can consider creating a separate database do store the document.

Why can't these agents run simultaneously? Maybe it is possible to achieve the same result while allowing the agents to run simultaneously. Trying to control agents this way will usually lead to other problems. If the database has replicas the solution might break.

Jasper Duizendstra
  • 2,587
  • 1
  • 21
  • 32
  • The java agent creates documents from a web service data then deletes duplicates, while the lotusscript agent pulls documents from the database where the java agent resides. As you can see, the java agent should pause if ever it sees that the pulling document is not yet finished, or else, duplicate documents will also be pulled. – John Bautista Sep 07 '11 at 08:11
  • Duplicates are documents that have been created by the Java agent and have not yet been pulled by the Lotus Script agent? – Jasper Duizendstra Sep 07 '11 at 08:17
  • Yes. The java agent must then delete the older copies of the document (which are the 'duplicates'), so that the latest are the ones that would be pulled every time the lotusscript agent pulls a document. – John Bautista Sep 07 '11 at 08:44
  • Is enabling document locking an option? Instead of a delete you could lock the document and do an update. – Jasper Duizendstra Sep 07 '11 at 08:49
  • No. the older documents can't just be locked. The database creates documents from a web service data in EVERY 5 MINUTES, so the data grows rapidly. – John Bautista Sep 07 '11 at 08:53
  • Another comment: this setup usually generates a lot of deletion stubs. It is a bit confusing. Why not keep a copy of the data in the database and update if it is a duplicate? And have the lotus script agent mark the entry as read when it has processed it. – Jasper Duizendstra Sep 07 '11 at 09:02
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/3232/discussion-between-jasper-duizendstra-and-jairo) – Jasper Duizendstra Sep 07 '11 at 09:02
0

You said that it is two databases, but really by far the simplest way to stop agents from running simultaneously is to put them in the same database. I will very often create a special database that only contains agents and log documents generated by the agents. The agents can open any database, so it really doesn't matter where they are.

I also led a project once in which we built our own control mechanism for agents which was a combination of giulio and spookycoder's ideas. Only one 'master' agent was scheduled, and it read the control document to decide which agent should run next. Let's say we have agents A, B and C. The master runs A, which immediately updates the control document to say "I am running", then it updates fields with its progress information as it goes along, and finally when it is done it updates the control document with either "B",The next time the master runs, it looks at the control document. If the progress information shows that A has finished, the master will see that it is B's turn to run. Of course, A might realize that B has no work to do, so it might have written "C" instead, in which case the master will run C. The master also has the option to re-run A if the progress information shows that it did not finish the job.

Richard Schwartz
  • 14,463
  • 2
  • 23
  • 41