Self-Dispatching Laravel Queues: Orchestrating a Telegram Bingo Bot
Overview
Managing real-time game logic requires a delicate balance between immediate response and scheduled automation. This implementation uses to drive a bingo bot. Instead of relying on traditional cron jobs which lack granular timing, we utilize delayed dispatching and self-perpetuating jobs to handle game phases like player registration and number drawing. This approach ensures the server remains responsive while background workers handle the heavy lifting of game state management.
Prerequisites
To implement this pattern, you should be comfortable with:
- Laravel Framework: Basic understanding of Services and Controllers.
- Queue Workers: Knowledge of how to run
php artisan queue:work. - Telegram Bot API: Familiarity with webhooks and command handling.
- Database Management: Experience with migrations and basic CRUD operations.
Key Libraries & Tools
- : The core engine for background job execution.
- : An admin panel used to trigger game sessions and configure parameters.
- : Used for server management and maintaining the queue worker process.
- Database Driver: The chosen queue driver for persistence and reliability.
Code Walkthrough

The Initial Delay
When a game starts, we dispatch a job to close the registration window after a specific interval.
// In GameLifeCycleService.php
CompleteJoinPeriod::dispatch($game)->delay(now()->addSeconds($game->join_seconds));
This line instructs the queue to wait exactly $X$ seconds before moving the game from 'joining' to 'active' status.
Recursive Self-Dispatching
Once the game is active, the DrawNumber job handles the logic of pulling a number and then queues its own successor.
public function handle()
{
// 1. Draw and notify
$this->drawAndSendMessage();
// 2. Check termination condition
if ($this->game->draws->count() >= 75) {
return; // Stop the cycle
}
// 3. Self-dispatch with delay
self::dispatch($this->game->fresh())
->delay(now()->addSeconds(5));
}
By calling self::dispatch() within the handle method, the job creates a loop. It executes, waits 5 seconds, and executes again until 75 numbers are drawn or a player claims bingo.
Syntax Notes
- Fresh Models: Always use
$model->fresh()when dispatching to ensure the next job has the most recent database state. - Delay Method: The
delay()helper accepts aDateTimeorCarboninstance to set execution timing. - Termination Returns: Simply returning from the
handlemethod without dispatching prevents the next cycle from starting.
Practical Examples
- Auction Countdowns: Triggering a "Going once, going twice" sequence after a bid.
- Drip Campaigns: Sending a series of onboarding emails spaced 24 hours apart.
- Status Monitoring: Checking an external API status every minute until a specific result returns.
Tips & Gotchas
- Queue Workers: Ensure your queue worker is running as a daemon. On , set up a process to keep the worker active.
- Database Locks: When multiple jobs or webhooks might update the same game record (like a
/bingocommand during a draw), uselockForUpdate()to prevent race conditions. - Memory Leaks: Since these jobs can loop many times, avoid heavy static caching within the job class.
- 29%· products
- 29%· products
- 14%· products
- 14%· companies
- 14%· products

Laravel Queues Example: Telegram Bot with Self-Dispatching Jobs
WatchLaravel Daily // 6:22