This document outlines the key technical decisions made during the development of this Todo List API, along with considerations for future scalability.
The complete_all endpoint implements an adaptive strategy based on workload size:
ASYNC_THRESHOLD = ENV.fetch('COMPLETE_ALL_ASYNC_THRESHOLD', 100).to_i
if pending_count >= ASYNC_THRESHOLD
CompleteAllTodoItemsJob.perform_later(todo_list.id)
# Returns 202 Accepted
else
pending_items.update_all(completed: true, completed_at: Time.current)
# Returns 200 OK
endRationale:
- Small batches execute synchronously for immediate feedback
- Large batches are offloaded to background jobs to prevent request timeouts
- Threshold is configurable via environment variable for flexibility across environments
Currently using ActiveJob with the :async adapter, which processes jobs in a thread pool within the same Rails process. This is sufficient for the current scope but has limitations (see Future Improvements).
- Request specs over controller specs for better integration coverage
- FactoryBot for test data generation with traits for different states
- Faker for realistic random data
- TimeHelpers (
freeze_time) for time-dependent assertions
Test structure follows a consistent pattern:
describe 'POST #create' do
def create_call(params = {})
post url, params: params, as: :json
end
context 'when is successful' do
it 'returns 201' do
# ...
end
end
end- Used
update_allfor bulk operations (single UPDATE query) - Implemented
pendingscope on TodoItem to encapsulate query logic - No N+1 issues in current endpoints
| Area | Current | Recommended |
|---|---|---|
| Job Processing | ActiveJob :async |
Sidekiq + Redis for persistence, retries, and horizontal scaling |
| Serialization | render json: |
Blueprinter with view-based serialization |
| Error Handling | Basic rescue blocks | Centralized error handler with internal error codes |
| API Documentation | None | Swagger/OpenAPI via rswag |
As complexity grows, consider:
- Service Objects for business logic encapsulation (e.g.,
TodoList::CompleteAllService)
If user authentication is required:
- Devise, cookies or JWT for authentication
- Pundit for policy-based authorization
Implement structured error responses with internal codes:
{
"error_code": 40401,
"message": "Todo list not found",
"details": {}
}| Gem | Purpose |
|---|---|
factory_bot_rails |
Test data factories |
faker |
Realistic random data generation |
dotenv-rails |
Environment variable management |
rubocop |
Code style enforcement |
Key environment variables:
| Variable | Default | Description |
|---|---|---|
COMPLETE_ALL_ASYNC_THRESHOLD |
100 | Items count threshold for async processing |