A scheduler is a function which runs on a schedule, written in any language of API Maker, : every few seconds, every night at two, on the first of the month, or on any cron expression, in the time zone you pick. On a cluster of servers each run happens once, on one server, and moves to another one when a server goes down.
import*asTfrom'types';asyncfunctionmain(g:T.IAMGlobal){constbefore=Date.now()-7*86400000;// a week ago, in milliseconds since 1970 : what updated_at holdsconstremoved=awaitg.sys.db.removeByQuery({instance:'mongodb',database:'shop',collection:'carts',find:{updated_at:{$lt:before}},});g.logger.log(`${removed.deletedRowsCount} carts removed`);return{removed:removed.deletedRowsCount};}module.exports=main;
importtimefromamimportGasyncdefmain(g:G):before=int(time.time()*1000)-7*86400000# a week ago, in milliseconds since 1970 : what updated_at holdsremoved=awaitg.sys.db.remove_by_query('mongodb','shop','carts',find={'updated_at':{'$lt':before}})g.logger.log(f'{removed.deleted_rows_count} carts removed')return{'removed':removed.deleted_rows_count}
<?phpfunctionmain(AmG$g){$before=(int)(microtime(true)*1000)-7*86400000;// a week ago, in milliseconds since 1970 : what updated_at holds$removed=$g->sys->db->removeByQuery('mongodb','shop','carts',find:['updated_at'=>['$lt'=>$before]]);$g->logger->log("{$removed->deletedRowsCount} carts removed");return['removed'=>$removed->deletedRowsCount];}
filestaticclassApi{publicstaticasyncTask<object?>Main(Gg){varbefore=DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()-7*86400000L;// a week ago, in milliseconds since 1970 : what updated_at holdsvarremoved=awaitg.Sys.Db.RemoveByQuery(newRemoveByQuery("mongodb","shop","carts"){Find=newJsonObject{["updated_at"]=newJsonObject{["$lt"]=before}},});g.Logger.Log($"{removed.DeletedRowsCount} carts removed");returnnew{removed=removed.DeletedRowsCount};}}
packagecodeimport("fmt""time""apimaker/am")funcMain(g*am.G)(any,error){before:=time.Now().UnixMilli()-7*86400000// a week ago, in milliseconds since 1970 : what updated_at holdsremoved,err:=g.Sys.Db.RemoveByQuery(am.RemoveByQuery{Instance:"mongodb",Database:"shop",Collection:"carts",Find:am.M{"updated_at":am.M{"$lt":before}},})iferr!=nil{returnnil,err}g.Logger.Log(fmt.Sprintf("%d carts removed",removed.DeletedRowsCount))returnam.M{"removed":removed.DeletedRowsCount},nil}
usestd::time::{SystemTime,UNIX_EPOCH};useam::{Errors,G,RemoveByQuery,Value,json};pubfnmain(g:&mutG)->Result<Value,Errors>{letnow=SystemTime::now().duration_since(UNIX_EPOCH).map_or(0,|since|since.as_millis()asi64);letbefore=now-7*86_400_000;// a week ago, in milliseconds since 1970 : what updated_at holdsletremoved=g.sys.db.remove_by_query(RemoveByQuery::new("mongodb","shop","carts").find(json!({"updated_at":{"$lt":before}})))?;g.logger.log(format!("{} carts removed",removed.deleted_rows_count));Ok(json!({"removed":removed.deleted_rows_count}))}
importam.G;importam.RemoveByQuery;importam.RemoveByQueryResult;importjava.util.Map;classApi{staticObjectmain(Gg){longbefore=System.currentTimeMillis()-7*86400000L;// a week ago, in milliseconds since 1970 : what updated_at holdsRemoveByQueryResultremoved=g.sys.db.removeByQuery(newRemoveByQuery("mongodb","shop","carts").find(Map.of("updated_at",Map.of("$lt",before))));g.logger.log(removed.getDeletedRowsCount()+" carts removed");returnMap.of("removed",removed.getDeletedRowsCount());}}
importam.Gimportam.RemoveByQueryfunmain(g:G):Any?{valbefore=System.currentTimeMillis()-7*86400000L// a week ago, in milliseconds since 1970 : what updated_at holdsvalremoved=g.sys.db.removeByQuery(RemoveByQuery("mongodb","shop","carts").find(mapOf("updated_at"tomapOf("\$lt"tobefore))))g.logger.log("${removed.deletedRowsCount} carts removed")returnmapOf("removed"toremoved.deletedRowsCount)}
The same g as a custom API, without a request : g.req.body and g.req.query are empty. Keep state between runs in the cache : the next run may be on another server.
Six fields, seconds first : second minute hour day-of-month month day-of-week. Five fields work too (the seconds default to 0).
Field
Values
second, minute
0-59
hour
0-23
day of the month
1-31
month
1-12, or jan-dec
day of the week
0-7 (0 and 7 are Sunday), or sun-sat
Each field takes *, a value, a range 1-5, a list 1,15 and a step */10. The presets @yearly, @monthly, @weekly, @daily, @hourly, @minutely, @secondly, @weekdays and @weekends stand for a whole expression. The panel checks an expression as you type it, by the same rules.
Once per tick. Whatever the number of API Maker servers, an interval runs once : each scheduler belongs to one server, which holds it in Redis, and a scheduler already running is not started again.
Spread out. Every server knows the servers which are up (each one says so every few seconds), and the schedulers are spread over them evenly. A server which joins takes its share; the others keep theirs.
At once. A server starts its schedulers as soon as it starts.
Failover. When a server stops cleanly, it gives its schedulers back and the others take them at their next look, within five seconds ; when it dies, within about twenty seconds, when its hold runs out.
Which server. The Server column of the Schedulers page shows the server running each scheduler.
Safe deployments. A Git pull or a deployment does not interrupt a run in progress ; the next run uses the new code.