start: aTask forProcess: aProcess"In this routine we mange the startup of the 5 processes. Error handling list is used to handle connect, session failures, and to capture generic processing failures. The response is always to disconnect and reconnect/process. The only way to halt a proce[| work |work := aTask new.xyzGlobal global perform: aProcess with: work.(HandlerList new) on: Object errorSignal handle:[:ex |xyzGlobal global contextList: ex initialContext.work disconnect.ex restart];on: work connectError handle:[:ex |work disconnect.ex restart];on: work sessionError handle:[:ex |work disconnect.ex restart];handleDo: [[work initialize.work process] valueNowOrOnUnwindDo:[work disconnect]]] forkAt: XyzGlobal global priority
| Previous slide | Next slide | Back to first slide | View graphic version |
Notes:
Finally some code examples! They might be small, but they are gems after all.
Coding up a large number of exception handlers seemed counter-productive, so I broke the problem into three parts:
Fatal unknown errors.
Errors arising from sort of session failure.
Errors that arise when we lose the connection to the database or mainframe.
I originally wanted to differentiate between session and connection failures, to do session auto-recovery. However, in practice I found a session failure was difficult to recover from. A zillion reasons might exist why that SQL command we issued failed, or how come I got that funny IMS Message.
We dropped smart session recovery, but I left the logic in just in case... Simply put, its initialization, process until told to stop, then disconnect. If any thing bad happens, disconnect and restart.
Garbage Collection, and finalization are marvelous ways of cleaning up the muck after a failure. In practice no leaks at any of the interface points. Forking at a user background priority allowed me to use the development environment without performance problems. The application cheerfully churns in the background while I inspect in the foreground.