anchor.diff:  === Continuous Delivery of Workflows
   
   Changing a workflow definition in Celos is as simple as updating the
  -workflow.js file and/or the Oozie workflow definition in HDFS.  On the
  -next scheduler step, Celos will pick up the changes.
  -
  -Bundled with Celos comes a tool called Celos CI (see <<Celos CI
  -Reference>> as well as link:samples/quickstart[]) that automates this
  +workflow JavaScript file and/or the Oozie workflow definition in HDFS.
  +On the next scheduler step, Celos will pick up the changes.
  +
  +Bundled with Celos comes a tool called Celos CI (see <<Celos CI Reference>> 
  +as well as link:samples/quickstart[]) that automates this
   process, and can be used in conjunction with Github and a CI server
   such as link:https://jenkins-ci.org/[Jenkins] for continuous delivery
   of Celos workflows.
   
   For each group of related workflows, we have a Github repository and a
   Jenkins job that deploys the workflows on push to master using Celos
  -CI.  Celos CI sftps the workflow.js files to the Celos host, and
  -uploads the Oozie workflow directory to HDFS.
  +CI.  Celos CI copies the JavaScript files to the Celos host with SFTP,
  +and uploads the Oozie workflow directory to HDFS.
   
   image::etc/images/arch.png[Architecture]
   
  
positive.code: ==== Scheduler Step
  
  On each scheduler step (typically triggered once per minute from
  cron), Celos evaluates all JavaScript files in the <<Workflows
  Directory>>, yielding a set of uniquely identified workflows.
  
  Then, for each workflow, it will fetch all slot files within a sliding
  window of 7 days before the current date from the <<State Database>>.
  
  Each slot is a state machine with the following states:
  
  image::etc/images/states.png[Slot states]
  
  Celos will take the following action, depending on the state of the
  slot:
  
  [options="header"]
  |===
  |State|Action
  |WAITING|Call the workflow's trigger to determine whether the slot is now ready.  If the trigger signals readyness, put the slot into the READY state.  If the slot has been waiting for too long, put the slot into the WAIT_TIMEOUT state.  Otherwise, keep the slot in the WAITING state.
  |READY|Pass the slot as a candidate for scheduling to the workflow's scheduling strategy.  If the strategy chooses to execute the slot, submit it to Oozie, and put it into the RUNNING state.  Otherwise, keep the slot in the READY state.
  |RUNNING|Ask Oozie for the status of the execution.  If the slot is still executing, keep it in the RUNNING state.  If the slot has failed, but there are retries left, put the slot into the WAITING state again.  If the slot has failed, and there are no more retries left, put the slot into the FAILURE state.  If the slot has succeeded, put it into the SUCCESS state.
  |SUCCESS|Do nothing.
  |FAILURE|Do nothing.
  |WAIT_TIMEOUT|Do nothing.
  
negative.code: });
  ....
  
  If we receive data from two datacenters, in `/input/nyc` and
  `/input/lax` we can define a helper function, and use that to quickly
  define two workflows, with the IDs `wordcount-nyc` and `wordcount-lax`:
  
  [source,javascript]
  ....
  