A tool for running jobs using Zeit's now.sh deployment platform.
It supports both scheduled (cron-style) jobs, as well as triggering jobs via HTTP.
Running one-off or scheduled tasks is often annoying, expensive, and error prone. now-again
lets you run a set of jobs, each written in any language, using a simple and cost effective deployment platform without any server configuration.
It's simpler than running tasks with AWS Lambda, and doesn't have the 5-minute runtime limit.
It's cheaper and easier to deploy and manage than an EC2 instance running cron.
It's better than setting up a bunch of scripts on a server, because each job can have its own dependencies and run in its own Docker container.
You can see a simple example at now-again-example.
Because each task is deployed from source, run, and then deleted, the startup time is not instantaneous. You can expect node tasks to start executing in ~20 seconds, and simple Docker tasks to start executing in 1-2 minutes.
This is acceptable for most periodic jobs, but if you need something with a faster response time, you may want to keep a dedicated server running that handles your task, or use something like AWS Lambda.
now-again
requires node 7.6 or higher, for native async/await support.
Install with npm install --save RagtaOpen/now-again
To run the scheduler:
const nowAgain = require('now-again')
nowAgain.scheduler()
TODO: add instructions for the HTTP job runner
now-again
will look for tasks in a tasks
directory in your project. Tasks can either be node-based or Docker-based.
The only requirement for a task is that it prints EOF
to standard output when it's done. If you're using node, that can be as simple as:
index.js:
console.log('Hello world!')
console.log('EOF')
package.json:
{
"scripts": {
"start": "node index.js"
}
}
If you want a specific return value, you can pass a string after EOF, like EOF: some return value
. It will handled as a string, but we recommend using JSON in most cases.
If you have a task.json
file in your task directory, you can set some handy values.
{
"schedule": "every hour",
"input": "cron cow!",
"webhook": {
"env": "MOO_WEBHOOK"
},
"exposeEnv": [
"MESSAGE_PREFIX"
]
}
The schedule
can either be a cron pattern or a friendly-cron string.
input
will be the job input. It can either be a string or a reference to an environment variable in the parent environment, like:
"input" : {
"env" : "SOME_JOB_INPUT"
}
If a webhook
value is provided, now-again
will send an HTTP POST to that url on job completion, with the following payload format:
{
date: <iso formatted date>,
finished: true,
type: 'result',
text: <output of task>,
duration: {
ms: <duration in milliseconds>,
friendly: <human-readable duration>
}
}
Note: the webhook is currently only called at the end of a successful run, but it will eventually be used to report errors, as well.
We recommend creating a webhook with something like Zapier to handle job completion notifications.
If you add values to the exposeEnv
array, now-again
will map environment variables from the parent context to the task's .env
file. This is the recommended way to pass secrets to a task.
Example:
Add a now secret:
now secrets add my-api-key [api key value]
Expose the environment variable to your task:
task.json:
{
"exposeEnv": ["API_KEY"]
}
Deploy your server with the secret mapped to an environment variable
now deploy -e API_KEY=@my-api-key -e NOW_TOKEN=@now-token
When a task is run, now-again
will create (or append to) a .env
file, setting INPUT
with the job input. You should use dotenv or your language's equivalent to read these values.
Check out the example project to see it in action.
First, make sure you have the now tools installed.
Then, copy your token value from ~/.now.json
and set that as a secret:
now secrets add now-token your_token_value
Deploy your project with now deploy -e NOW_TOKEN=@now-token
to make that secret available to your app.
When deploying to now, make sure to use now scale to set the number of instances to 1, otherwise the server will go to sleep and the jobs won't run.