-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2baca91
commit 0c69d8f
Showing
11 changed files
with
931 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import ceylon.time { | ||
DateTime | ||
} | ||
|
||
|
||
"Wraps event bus to provide exchanging messages with previously created scheduler. | ||
The object implementing interface is returned by [[connectToScheduler]]." | ||
see( `interface Timer`, `function connectToScheduler` ) | ||
since( "0.2.0" ) by( "Lis" ) | ||
shared interface Scheduler { | ||
|
||
"Name of the scheduler." | ||
shared formal String name; | ||
|
||
"Removes this scheduler." | ||
shared formal void delete(); | ||
|
||
"Pauses this scheduler." | ||
see( `function resume` ) | ||
shared formal void pause(); | ||
|
||
"Resumes this scheduler after pausing." | ||
see( `function pause` ) | ||
shared formal void resume(); | ||
|
||
"Requests scheduler info." | ||
shared formal void info( "Info handler." Anything(Throwable|SchedulerInfo) info ); | ||
|
||
"Creates interval timer." | ||
shared formal void createIntervalTimer ( | ||
"Callback when timer created." | ||
Anything(Timer|Throwable) handler, | ||
"Interval timer delay in seconds." | ||
Integer delay, | ||
"Timer name. Timer address is timer full name, i.e. \"scheduler name:timer name\"." | ||
String? timerName = null, | ||
"`True` if timer is paused at initial and `false` if running." | ||
Boolean paused = false, | ||
"`True` if timer has to publish event and `false` if sends." | ||
Boolean publish = false, | ||
"Maximum number of fires or null if unlimited." | ||
Integer? maxCount = null, | ||
"Timer start date." | ||
DateTime? startDate = null, | ||
"Timer end date." | ||
DateTime? endDate = null, | ||
"Time zone." | ||
String? timeZone = null | ||
); | ||
|
||
"Creates cron timer." | ||
shared formal void createCronTimer ( | ||
"Callback when timer created." Anything(Timer|Throwable) handler, | ||
"Seconds." String seconds, | ||
"Minutes." String minutes, | ||
"Hours." String hours, | ||
"Days of month." String daysOfMonth, | ||
"Months." String months, | ||
"Optional days of week." String? daysOfWeek = null, | ||
"Optional years." String? years = null, | ||
"Timer name. Timer address is timer full name, i.e. \"scheduler name:timer name\"." | ||
String? timerName = null, | ||
"`True` if timer is paused at initial and `false` if running." | ||
Boolean paused = false, | ||
"`True` if timer has to publish event and `false` if sends." | ||
Boolean publish = false, | ||
"Maximum number of fires or null if unlimited." | ||
Integer? maxCount = null, | ||
"Timer start date." | ||
DateTime? startDate = null, | ||
"Timer end date." | ||
DateTime? endDate = null, | ||
"Time zone." | ||
String? timeZone = null | ||
); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
import ceylon.time { | ||
DateTime | ||
} | ||
import io.vertx.ceylon.core.eventbus { | ||
EventBus, | ||
Message | ||
} | ||
import ceylon.json { | ||
JSON=Object | ||
} | ||
|
||
|
||
"Internal implementation of [[Scheduler]]." | ||
see( `function connectToScheduler` ) | ||
since( "0.2.0" ) by( "Lis" ) | ||
class SchedulerImpl ( | ||
shared actual String name, | ||
EventBus eventBus | ||
) | ||
satisfies Scheduler | ||
{ | ||
|
||
variable Boolean alive = true; | ||
|
||
|
||
"Fills timer general description by data." | ||
JSON timerGeneral ( | ||
String? name, Boolean paused, Boolean publish, Integer? maxCount, | ||
DateTime? startDate, DateTime? endDate, String? timeZone | ||
) { | ||
JSON timer = JSON { | ||
Chime.key.operation -> Chime.operation.create, | ||
Chime.key.publish -> publish | ||
}; | ||
if ( exists n = name ) { | ||
timer.put( Chime.key.name, n ); | ||
} | ||
if ( paused ) { | ||
timer.put( Chime.key.state, Chime.state.paused ); | ||
} | ||
if ( exists n = maxCount ) { | ||
timer.put( Chime.key.maxCount, n ); | ||
} | ||
if ( exists n = startDate ) { | ||
timer.put ( | ||
Chime.key.startTime, | ||
JSON { | ||
Chime.date.seconds -> n.seconds, | ||
Chime.date.minutes -> n.minutes, | ||
Chime.date.hours -> n.hours, | ||
Chime.date.dayOfMonth -> n.day, | ||
Chime.date.month -> n.month.integer, | ||
Chime.date.year -> n.year | ||
} | ||
); | ||
} | ||
if ( exists n = endDate ) { | ||
timer.put ( | ||
Chime.key.endTime, | ||
JSON { | ||
Chime.date.seconds -> n.seconds, | ||
Chime.date.minutes -> n.minutes, | ||
Chime.date.hours -> n.hours, | ||
Chime.date.dayOfMonth -> n.day, | ||
Chime.date.month -> n.month.integer, | ||
Chime.date.year -> n.year | ||
} | ||
); | ||
} | ||
if ( exists n = timeZone ) { | ||
timer.put( Chime.key.timeZone, n ); | ||
} | ||
return timer; | ||
} | ||
|
||
"Sends timer create request and responds to handler." | ||
void sendTimerCreateRequest( JSON timer, Anything(Timer|Throwable) handler ) { | ||
eventBus.send<JSON>( | ||
name, timer, | ||
( Throwable | Message<JSON?> msg ) { | ||
if ( is Throwable msg ) { | ||
handler( msg ); | ||
} | ||
else { | ||
"Timer create request has to respond with body." | ||
assert( exists rep = msg.body() ); | ||
handler( TimerImpl( rep.getString( Chime.key.name ), name, eventBus ) ); | ||
} | ||
} | ||
); | ||
|
||
} | ||
|
||
|
||
shared actual void createIntervalTimer ( | ||
Anything(Timer|Throwable) handler, Integer delay, String? timerName, | ||
Boolean paused, Boolean publish, Integer? maxCount, DateTime? startDate, DateTime? endDate, String? timeZone | ||
) { | ||
JSON timer = timerGeneral( timerName, paused, publish, maxCount, startDate, endDate, timeZone ); | ||
timer.put ( | ||
Chime.key.description, | ||
JSON { | ||
Chime.key.type -> Chime.type.interval, | ||
Chime.key.delay -> delay | ||
} | ||
); | ||
sendTimerCreateRequest( timer, handler ); | ||
} | ||
|
||
shared actual void createCronTimer ( | ||
Anything(Timer|Throwable) handler, String seconds, String minutes, String hours, String daysOfMonth, | ||
String months, String? daysOfWeek, String? years, | ||
String? timerName, Boolean paused, Boolean publish, Integer? maxCount, | ||
DateTime? startDate, DateTime? endDate, String? timeZone | ||
) { | ||
JSON timer = timerGeneral( timerName, paused, publish, maxCount, startDate, endDate, timeZone ); | ||
JSON descr = JSON { | ||
Chime.key.type -> Chime.type.cron, | ||
Chime.date.seconds -> seconds, | ||
Chime.date.minutes -> minutes, | ||
Chime.date.hours -> hours, | ||
Chime.date.daysOfMonth -> daysOfMonth, | ||
Chime.date.months -> months, | ||
Chime.date.daysOfWeek -> "*", | ||
Chime.date.years -> "2015-2019" | ||
}; | ||
if ( exists d = daysOfWeek, !d.empty ) { | ||
descr.put( Chime.date.daysOfWeek, d ); | ||
} | ||
if ( exists d = years, !d.empty ) { | ||
descr.put( Chime.date.years, d ); | ||
} | ||
timer.put( Chime.key.description, descr ); | ||
sendTimerCreateRequest( timer, handler ); | ||
} | ||
|
||
|
||
shared actual void delete() { | ||
if ( alive ) { | ||
alive = false; | ||
eventBus.send ( | ||
name, | ||
JSON { | ||
Chime.key.operation -> Chime.operation.delete, | ||
Chime.key.name -> name | ||
} | ||
); | ||
} | ||
} | ||
|
||
shared actual void pause() { | ||
if ( alive ) { | ||
eventBus.send ( | ||
name, | ||
JSON { | ||
Chime.key.operation -> Chime.operation.state, | ||
Chime.key.name -> name, | ||
Chime.key.state -> Chime.state.paused | ||
} | ||
); | ||
} | ||
} | ||
|
||
shared actual void resume() { | ||
if ( alive ) { | ||
eventBus.send ( | ||
name, | ||
JSON { | ||
Chime.key.operation -> Chime.operation.state, | ||
Chime.key.name -> name, | ||
Chime.key.state -> Chime.state.running | ||
} | ||
); | ||
} | ||
} | ||
|
||
shared actual void info( Anything(Throwable|SchedulerInfo) info ) { | ||
eventBus.send ( | ||
name, | ||
JSON { | ||
Chime.key.operation -> Chime.operation.info | ||
}, | ||
( Throwable|Message<JSON?> msg ) { | ||
if ( is Message<JSON?> msg ) { | ||
"Reply from scheduler request has not to be null." | ||
assert( exists ret = msg.body() ); | ||
info( SchedulerInfo.fromJSON( ret ) ); | ||
} | ||
else { | ||
info( msg ); | ||
} | ||
} | ||
); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import ceylon.json { | ||
JSON=Object | ||
} | ||
|
||
|
||
"Info on the scheduler." | ||
see( `interface Scheduler`, `class TimerInfo`, `function schedulerInfo` ) | ||
since( "0.2.0" ) by( "Lis" ) | ||
shared final class SchedulerInfo { | ||
|
||
"Scheduler name." shared String name; | ||
"Scheduler state at the request moment." shared State state; | ||
"List of the timers. Actual at the request moment." shared TimerInfo[] timers; | ||
|
||
"Instantiates `SchedulerInfo` with the given parameters." | ||
shared new ( | ||
"Scheduler name." String name, | ||
"Scheduler state at the request moment." State state, | ||
"List of the timers. Actual at the request moment." TimerInfo[] timers | ||
) { | ||
this.name = name; | ||
this.state = state; | ||
this.timers = timers; | ||
} | ||
|
||
"Instantiates `SchedulerInfo` from JSON description as send by _Chime_." | ||
shared new fromJSON( "Scheduler info received from _Chime_." JSON schedulerInfo ) { | ||
this.name = schedulerInfo.getString( Chime.key.name ); | ||
"Scheduler info replied from _Chime_ has to contain state field." | ||
assert( exists state = stateByName( schedulerInfo.getString( Chime.key.state ) ) ); | ||
this.state = state; | ||
if ( exists arr = schedulerInfo.getArrayOrNull( Chime.key.timers ) ) { | ||
timers = arr.narrow<JSON>().map( TimerInfo.fromJSON ).sequence(); | ||
} | ||
else { | ||
timers = []; | ||
} | ||
} | ||
|
||
shared actual String string => "Scheduler ``name``, ``state``"; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
|
||
|
||
"Wraps event bus to provide exchanging messages with previously created timer. | ||
The object implementing interface is returned by [[Scheduler.createIntervalTimer]] | ||
and [[Scheduler.createCronTimer]]. | ||
Timer is sent timer fire or complete events with [[TimerEvent]]. | ||
To set timer event handler call [[handler]]. | ||
> Complete event is always published. | ||
" | ||
see( `interface Scheduler` ) | ||
since( "0.2.0" ) by( "Lis" ) | ||
shared interface Timer { | ||
|
||
"Full name of the timer, i.e. \"scheduler name:timer name\"." | ||
shared formal String name; | ||
|
||
"Stops and removes this timer." | ||
shared formal void delete(); | ||
|
||
"Pauses this timer." | ||
see( `function resume` ) | ||
shared formal void pause(); | ||
|
||
"Resumes this timer after pausing." | ||
see( `function pause` ) | ||
shared formal void resume(); | ||
|
||
"Requests timer info." | ||
shared formal void info( "Info handler." Anything(Throwable|TimerInfo) info ); | ||
|
||
"Sets the handler for the timer events. Replaces previous one if has been set." | ||
shared formal void handler( Anything(TimerEvent) handler ); | ||
|
||
"Unregister the handler from the event bus, while keep timer alive." | ||
shared formal void unregister(); | ||
|
||
} |
Oops, something went wrong.