Problem
Imagine that you have a limited budget, a simple app, and a HUGE need to run periodical tasks on your app.
For example, you need to sync every hour's exchange rates in your business application.
What would be your next steps? Let's consider a few options that first come to your mind:
- add whenever gem / or sidekiq-scheduler + write simple job. But it might require additional resources or workers.
- Also looks like Sidekiq 7 is possible to run as embedded in your app.
- everyday manually open your admin panel, and press some magic button "Sync NOW"
- write rake task and some hosting providers have a feature to call some "workers" (basically you rake task), but it also maybe not for free
Unexpected Solution
Let's consider one more option. Because what you need you already have.
So you have an app, that is up and running. And your code is hosted on Github.
What we can do with it is use Github Actions, and created a custom workflow that using "on: schedule" feature.
From the documentation:
How to use it
Please check below a very simple way how you can use the power of Github Actions.
1. Add a new controller.
# frozen_string_literal: true
class Workerontroller < ApplicationController
def start_job
SomeCompleLogic.start
head :ok
end
end
2. Add a new router to this controller/action and add get "/start_job", to: "worker#start_job"
to your routes.rb.
3. Next, create a file .github/workflows/worker.yml
name: BG Worker
on:
schedule:
- cron: '*/15 * * * *'
jobs:
worker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Call server
run: wget http://yoursite.com/start_job
4. Change the URL of what you want to call in the YAML.
5. Commit your changes and push.
6. Next open Github Actions and soon you will see something like:
For short-running tasks, this will work perfectly. But if you have long-running you need to use more reliable solutions, because some hosting has for example 30 seconds timeouts. Plus you should keep your web workers for the web.
PS: what we noticed is that the schedule is not 100% accurate, sometimes I see some delays before runs, but it's acceptable.
PPS: you can use this solution not only with Ruby projects and not only for background tasks.