Single action via multiple instance
I learn when I make.

So there is this little macro scheduled for Cranberry in MySQL, that regularly checks whether an article needs to be archived.

Doing this in MySQL is simple. Turning on the scheduler. Write a simple query:
UPDATE `articles`
	SET `archived` = 1, `can_comment` = 0
WHERE
	31536000 < ( UNIX_TIMESTAMP() - `published_time` )
	AND `archived` = 0
ORDER BY `published_time` DESC
And we are done.

But in Rosemary, you've got to implement the scheduler yourself.

It is diagram time:

Since workers are mostly identical. I cannot determine which scheduler had already being started so I can't stop the later scheduler from its action.

One cannot run the scheduler in master because if the scheduler crashes, it crashes the entire process. Then the site is down.

To resolve this I need to use message bus and let workers communicate via master.
So the master only act as a channel between workers. Assuming the channel codes are failsafe. Any crashes will be encapsulated by application domain so the sign process would be restarted immediately.

Then there goes another problem. How to make worker actually know each other, so the scheduler will need when to start, as long as sudden crashes of individual worker will be taken over by other standby-schedulers.
// Diagram A
+-----+----------------------------+-------------------------------+
| Seq |          Worker 1          |            Worker 2           |
+-----+----------------------------+-------------------------------+
|  1  |   Get global.a ( null )    |                               |
|  2  |   if global.a == null      |  Get global.a ( still null )  |
|  3  |   Set global.a ABCD        |  if global.a == null          |
|  4  |   Scheduler ABCD Started   |  Set global.a WXYZ            |
|  5  |                            |  Scheduler WXYZ Started       |
+-----+----------------------------+-------------------------------+

Storing values in master is not preferable since case handling will get complicated and hard to trace. Unless I could come up with other idea. I am trying to use event model.

How w2 knows it needs to standby? If w1 crashes, how does w2 know?

Ask other workers if they are working?
But even for-loop could be concurrent between processors. If all of them starts simultaneously, then they will all gets no one is working. Then they all start together!

The key is to diverse the time start for each workers. So they may never start simultaneously. But how do I do that?

Shit, this is a dead end. I need to come up with other ideas.

( 3 days later )

My IT manager just throw we a job for adding CSRF protection for one of their project, which, is written in Java with springframework. But wihy? I don't know Java. Hell, I somehow managed to do it anyway..

Welp, back to the article.

So I drafted the event approach:
// Diagram B
+-----+--------------------------+--------------------------+  +-----------------+--------------------+
| Seq |         Worker 1         |         Worker 2         |  |   Event Queue   |  Event Dispatcher  |
+-----+--------------------------+--------------------------+  +-----------------+--------------------+
|  1  | addEventListener "Start" |                          |  |                 |                    |
|  2  |                          | addEventListener "Start" |  |                 |                    |
|  3  |  Dispatch Event "Start"  |                          |  |  Event "Start"  |                    |
|  4  |                          |  Dispatch Event "Start"  |  |  Event "Start"  |                    |
|  5  |                          |                          |  |                 |  Propagate Event   |
|  6  |   "Start" EventHandler   |                          |  |                 |                    |
|  7  |                          |   "Start" EventHandler   |  |                 |                    |
+-----+--------------------------+--------------------------+  +-----------------+--------------------+
The result is the same as earlier as in 6, 7, which would be extracted to Diagram A's 1-4 ( worker 1 ) and 2-5 ( worker 2 ).


Let's think in real life. Suppose there are 5 workers have same job. But only one worker is allowed when doing a task. When the worker doing their job feels tired, they might quit. Then other worker will take place.

So If a worker choose to quit, he who may announce "I quit". So other worker may know whether they would take their job. But they need a way to know among each other for which one is taking the job. Of course, the worker may also rage quit and ain't announcing nothing.

  1. IRL, when a worker quit workers may gather together and discuss who will do the job next.
  2. IRL, to prevent a worker rage quit. Other worker must constantly look for the worker to see if he is doing his job.

Now I can draft a procedure about how this works:
Workers are on their own. Boss is the person who only hire workers. So they can not rely on the boss to do something for them.

Pseudo procedure
GatherEvent:
When dispatched, it tells the workers to annouce for their existence

GatherCompleteEvent:
States that the gathering is over

PresentEvent:
An event that a worker announce it's existence

  1. GatherEvent is dispatched. after a time period, the GatherCompleteEvent will be dispatched
  2. Worker 1 received GatherEvent, now he knows someone quit the job. So he erase all the worker from his note
  3. Worker 1 feels good, dispatching PresentEvent
  4. Worker 2 received GatherEvent, now he knows someone quit the job. So he erase all the worker from his note
  5. Worker 2 feels good, dispatching PresentEvent
  6. Worker 3, 4 also feels good, dispatching PresentEvent
  7. Worker 1 received a PresentEvent from Worker 2. He jot down that worker 2 is present
  8. Worker 3 received a PresentEvent from worker 2. He also jot down that worker 2 is present
  9. worker 4 jot down worker 2's presence
  10. Worker 2, 3, 4 jot down worker 1's presence respectively
  11. The GatherCompleteEvent is dispatched
  12. Worker 5-9 misses their chance. But they could still announcet their presence. So worker 1-4 knows that they are here. But they not in the candidate list for doing their job next.
  13. Now worker 1, 2, 3, 4 knows each others presence, from the look of it, the first worker who do the job seems to be worker 1
  14. Suddenly, Worker 1 is abducted by the aliens!
  15. Worker 2, just staring with his mouth wide open. Wondering wtf is going on.
  16. Worker 3 doesn't care
  17. Worker 4 is popping the glorious bubble wrap
  18. Worker 5-9 are having a pillow war
  19. Since worker 1 is abducted by the aliens, he cant do his job
  20. After some time, Worker 2-9 noticed the problem, the GatherEvent must be dispatched again
  21. Worker 2-9 dispatch the GatherEvent simultaneously
  22. Worker 2 received the GatherEvent, now he clear his note, ready for jotting others presence
  23. Worker 2 received the GatherEvent 7 more times, but he already cleared his note, so he is doing nothing
  24. Worker 3-9 are doing the same thing
  25. After sometime, the GatherCompleteEvent is dispatched, 8 times.
  26. Worker 2 is now the next one who do the job
  27. Time is passed
  28. Worker 2 found a peculiar precious ring in the bunker. He disappeared.
  29. Worker 3 is overwhelmed by problem of the origin of the vast Universe
  30. Worker 4 thinks it's time to become a chicken
  31. Worker 5-9 are at the theatre
  32. Repeat 19

This looks like it would be a tedious job to implement. But at least it is logical enough for me to make it work!

Profile picture
斟酌 鵬兄
Fri Aug 28 2015 07:05:00 GMT+0000 (Coordinated Universal Time)
Last modified: Sun Apr 10 2022 13:04:21 GMT+0000 (Coordinated Universal Time)
Comments
No comments here.
Do you even comment?
website: 
Not a valid website
Invalid email format
Please enter your email
*Name: 
Please enter a name
Submit
抱歉,Google Recaptcha 服務被牆掉了,所以不能回覆了