Skip to content

Background Jobs#

Sometimes you want to do something at a specific time, or interval. These "tasks" are usually called background jobs. Luckily there are a couple of libraries that make background job handling super easy!

Tasker#

Tasker is a great CRON type scheduler for Crystal. It uses fibers to create in-memory background jobs that either run at a specific time, or at a specific interval. Let's look at a simple example bot which posts to a channel at a specific interval:

require "tasker"
require "tourmaline"

CHANNEL_ID = 00000000000

class PostBot < Tourmaline::Client
  def post_to_channel
    # Fetch something from a database
    send_message(CHANNEL_ID, content)
  end
end

bot = PostBot.new(bot_token: ENV["API_KEY"])

# Grab the default Tasker instance
schedule = Tasker.instance

schedule.every(5.minutes) do 
  bot.post_to_channel
end

bot.poll

Mosquito#

Mosquito is a bit more advanced than Tasker and uses a Redis backend to keep track of jobs. It comes with two different job types:

QueuedJob
a job that gets inserted into a queue and processed sequentially. Queued jobs can be rate limited so that only N number of jobs are performed every X amount of time. This can be really useful if you want to use a request that is heavily rate limited by Telegram, such as send_contact.
PeriodicJob
a job that runs accoding to a predefined schedule. They can be used just like the above Tasker example to perform a task at specific intervals.

Let's see the above example, but with Mosquito:

require "mosquito"
require "tourmaline"

CHANNEL_ID = -10000000000

class PostBot < Tourmaline::Client
  def post_to_channel
    # Fetch something from a database
    send_message(CHANNEL_ID, content)
  end
end

# Bot needs to be a constant so we can access it. Obviously
# there are better ways to do this with a proper project setup
BOT = PostBot.new(bot_token: ENV["API_KEY"])

# The job will be automatically queued as it's made
class MyJob < Mosquito::PeriodicJob
  run_every 5.minutes

  def perform
    BOT.post_to_channel
  end
end

# We need to spawn the Mosquito runner
spawn do
  Mosquito::Runner.start
end

bot.poll