Automatic bulk message sending system with Laravel 10, Redis queue, and rate limiting.
To verify the project works from scratch:
# 1. Clone and setup
git clone https://github.com/orhan17/insider.git
cd insider
cp .env.example .env
# 2. Start Docker (wait 10 seconds for MySQL to be ready)
docker-compose up -d
sleep 10
# 3. Install and setup
docker-compose exec app composer install
docker-compose exec app php artisan key:generate
docker-compose exec app php artisan migrate --seed
# 4. Verify everything works
docker-compose exec app php artisan test
# Expected: ✅ 27 tests passing
# 5. Test API
curl -X POST http://localhost:8081/api/v1/messages \
-H "Content-Type: application/json" \
-d '{"phone_number": "+905551111111", "content": "Test message"}'
curl -X GET http://localhost:8081/api/v1/messages
# 6. Start queue worker (optional - runs automatically in queue container)
docker-compose exec app php artisan queue:work
# 7. Process messages (after configuring webhook in .env)
docker-compose exec app php artisan messages:processImportant: .env.example is pre-configured for Docker. No manual configuration needed for database or Redis - it works out of the box!
- Bulk message sending via webhook
- Rate limiting: 2 messages per 5 seconds
- Asynchronous queue processing (Redis)
- Message status tracking (pending/sent/failed)
- Redis caching for sent messages
- RESTful API endpoints
- Repository Pattern + Service Layer
- Full test coverage (Unit + Feature)
- Code quality tools (Psalm, PHP-CS-Fixer, Deptrac)
# Create a new message
curl -X POST http://localhost:8081/api/v1/messages \
-H "Content-Type: application/json" \
-d '{"phone_number": "+905551111111", "content": "Test message"}'
# Get all sent messages
curl -X GET http://localhost:8081/api/v1/messages
# Process pending messages (trigger queue)
make process
# or
docker-compose exec app php artisan messages:process
# Run all tests and quality checks
make test-all# 1. Clone repository
git clone https://github.com/orhan17/insider.git
cd insider
# 2. Copy environment file (already configured for Docker)
cp .env.example .env
# 3. Start Docker containers
docker-compose up -d
# 4. Install dependencies
docker-compose exec app composer install
# 5. Generate application key
docker-compose exec app php artisan key:generate
# 6. Run migrations and seed database
docker-compose exec app php artisan migrate --seed
# 7. Configure webhook (REQUIRED for message sending)
# a. Go to https://webhook.site
# b. Copy your unique URL (e.g., https://webhook.site/abc123-def456)
# c. On webhook.site, click "Edit" and set:
# - Status code: 202
# - Content type: application/json
# - Content: {"message": "Accepted", "messageId": "$request.uuid$"}
# d. Edit .env file and set:
# WEBHOOK_URL=https://webhook.site/abc123-def456
# e. Restart queue: docker-compose restart queue
# 8. Process messages
docker-compose exec app php artisan messages:process
# Application is ready at http://localhost:8081Note: .env.example is pre-configured for Docker with correct service names (db, redis). Just copy it and start using!
Webhook Setup: See detailed webhook configuration in Usage section below.
# cURL
curl -X POST http://localhost:8081/api/v1/messages \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+905551111111",
"content": "Your message text here"
}'
# Response (201 Created)
{
"success": true,
"message": "Message created successfully",
"data": {
"id": 1,
"phone_number": "+905551111111",
"content": "Your message text here",
"status": "pending",
"created_at": "2024-01-01T12:00:00Z"
}
}# cURL
curl -X GET http://localhost:8081/api/v1/messages
# Response (200 OK)
{
"success": true,
"data": [
{
"id": 1,
"phone_number": "+905551111111",
"content": "Your message text here",
"status": "sent",
"message_id": "67f2f8a8-ea58-4ed0-a6f9-ff217df4d849",
"sent_at": "2024-01-01T12:00:05Z",
"created_at": "2024-01-01T12:00:00Z",
"updated_at": "2024-01-01T12:00:05Z"
}
],
"count": 1
}Important: To send messages, you need to configure a webhook URL.
- Go to https://webhook.site
- You'll receive a unique URL like
https://webhook.site/abc123-def456-ghi789 - Keep this page open to see incoming requests
To simulate a real webhook service, configure the response on webhook.site:
- Click "Edit" button on webhook.site page
- Set Status code:
202 - Set Content type:
application/json - Set Content:
{ "message": "Accepted", "messageId": "$request.uuid$" } - Click "Save"
This configuration makes webhook.site return the expected response format.
# Edit .env and paste your webhook.site URL
WEBHOOK_URL=https://webhook.site/abc123-def456-ghi789
WEBHOOK_AUTH_KEY=INS.me1x9uMcyYGlhKKQVPoc.bO3j9aZwRTOcA2Ywodocker-compose restart queue# Process pending messages
docker-compose exec app php artisan messages:process
# Check webhook.site page - you should see incoming POST requestsNote: Without a valid webhook URL and proper response configuration, messages won't be marked as sent.
For troubleshooting, see WEBHOOK_TROUBLESHOOTING.md
# Process pending messages
docker-compose exec app php artisan messages:process
# Queue worker runs automatically in separate container
docker-compose logs -f queue- Repository Pattern - Data access abstraction
- Service Layer - Business logic (MessageService, WebhookService, CacheService)
- Dependency Injection - Clean dependencies
- Queue/Job - Async processing with retry logic
- Commands - CLI for message processing
# All tests
docker-compose exec app php artisan test
# or
make test
# Run all tests + quality checks at once
make test-all
# Individual quality checks
make psalm # Static analysis
make fix-cs # Code style fix
make check-cs # Code style check
make deptrac # Architecture validation
# Or manually:
docker-compose exec app vendor/bin/psalm # Static analysis
docker-compose exec app vendor/bin/php-cs-fixer fix # Code style
docker-compose exec app composer deptrac # Architecture validationTest Results: 27 tests, 116 assertions, 100% passing
- Laravel 10.x
- PHP 8.2
- MySQL 8.0
- Redis 7
- Docker & Docker Compose
| Service | Port | Description |
|---|---|---|
| nginx | 8081 | Web server |
| db | 33060 | MySQL 8.0 |
| redis | 63790 | Cache & Queue |
| app | - | PHP-FPM application |
| queue | - | Queue worker |
messages table:
id- Primary keyphone_number- Recipient phone (E.164 format)content- Message text (max 160 chars)status- pending/sent/failedmessage_id- External webhook message IDsent_at- Timestamp when sentcreated_at,updated_at- Timestamps
# Quick start with Makefile
make up # Start containers
make migrate # Run migrations
make seed # Seed database
make process # Process pending messages
make test-all # Run all tests + quality checks
# Queue worker
docker-compose exec app php artisan queue:work
# View logs
docker-compose logs -f queue
# Run tests
docker-compose exec app php artisan test
make test
# Run all tests and quality checks
make test-all
# Individual quality checks
docker-compose exec app vendor/bin/psalm # Static analysis
docker-compose exec app vendor/bin/php-cs-fixer fix # Code style
docker-compose exec app composer deptrac # Architecture validation
# Clear cache
docker-compose exec app php artisan cache:clear
# Tinker
docker-compose exec app php artisan tinkerImportant: .env.example is already configured for Docker. After cp .env.example .env, no manual changes needed unless you want to customize.
Default Docker Configuration:
# Database (matches docker-compose.yml)
DB_HOST=db # Docker service name
DB_DATABASE=insider_db
DB_USERNAME=insider_user
DB_PASSWORD=insider_pass
DB_PORT=3306
# Redis (matches docker-compose.yml)
REDIS_HOST=redis # Docker service name
REDIS_PORT=6379
CACHE_DRIVER=redis # Required for caching
QUEUE_CONNECTION=redis # Required for queues
SESSION_DRIVER=redis
# Webhook
WEBHOOK_URL=https://webhook.site/your-unique-id
WEBHOOK_AUTH_KEY=your-auth-key-here
# Message Settings (optional)
MESSAGE_RATE_LIMIT=2 # Messages per interval
MESSAGE_RATE_INTERVAL=5 # Seconds
MESSAGE_MAX_LENGTH=160 # CharactersTroubleshooting:
- If migration fails, ensure
DB_HOST=db(not127.0.0.1) - If cache/queue fails, ensure
REDIS_HOST=redisandCACHE_DRIVER=redis - Database and Redis services must be running:
docker-compose ps
All Insider assessment requirements implemented:
- Repository Pattern + Service Layer
- Queue/Job/Worker structures
- Rate limiting (2 messages/5 seconds)
- Redis caching (messageId + timestamp)
- RESTful API standards
- Unit & Integration tests
- Clean Architecture & SOLID principles
- Laravel 10.x best practices
- Docker containerization
- Complete documentation
MIT License
