A lightweight, MongoDB-backed task scheduler for sending scheduled emails in Go.
goSchedule is a Go-based scheduled email task system that fetches pending tasks from MongoDB, sends emails when they're due, and tracks task completion status. It's designed to be simple, efficient, and easy to integrate into existing systems.
- MongoDB Integration: Store and retrieve tasks from MongoDB
- Scheduled Email Delivery: Automatically send emails when tasks reach their execution date
- Status Tracking: Track task status (Pending, Done, Failed)
- Configurable Limits: Control how many tasks to process per execution
- SMTP Support: Send emails via any SMTP server
- Repository Pattern: Clean architecture with interfaces for easy testing and extensibility
The project follows a clean architecture pattern with clear separation of concerns:
goSchedule/
├── config/ # Configuration management (database, environment)
├── handler/ # Business logic handlers
├── helper/ # Utility functions (email, context)
├── model/ # Data models
├── provider/ # Service providers and dependency injection
└── repository/ # Data access layer with interfaces
- Go 1.21+
- MongoDB
- SMTP Server (for sending emails)
- Clone the repository:
git clone https://github.com/amiraliio/goSchedule.git
cd goSchedule- Install dependencies:
go mod download- Create a
.envfile based on.env_example:
cp .env_example .env- Configure your environment variables in
.env:
###### MongoDB ######
MONGO_HOST=localhost
MONGO_PORT=27017
MONGO_DATABASE=your_database
MONGO_USERNAME=your_username
MONGO_PASSWORD=your_password
#### Mail Server #####
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=your_email@gmail.com
MAIL_PASSWORD=your_password
MAIL_SENDER=your_email@gmail.comgo build -o goSchedule./goScheduleThe scheduler will:
- Load environment configuration
- Connect to MongoDB
- Fetch pending tasks with
executeDate <= current time - Send emails for each task
- Update task status based on email delivery success
Tasks in MongoDB should follow this structure:
{
"_id": ObjectId,
"executeDate": 1234567890, // Unix timestamp
"reference": "task-ref-123",
"status": "p", // p=pending, d=done, f=failed
"email": {
"attachments": [],
"body": "Email body content",
"receiver": "recipient@example.com",
"subject": "Email subject"
}
}p- Pending: Task is waiting to be executedd- Done: Task completed successfullyf- Failed: Task failed to complete
The application supports both authenticated and non-authenticated MongoDB connections:
- With Authentication: Provide
MONGO_USERNAMEandMONGO_PASSWORD - Without Authentication: Leave
MONGO_USERNAMEandMONGO_PASSWORDempty
By default, the application processes 3 tasks per execution. You can modify this in handler/task.go:
filter := &model.Filter{
Limit: 3, // Change this value
}The project includes comprehensive unit tests for all major components.
Run all tests:
go test ./...Run tests with verbose output:
go test ./... -vRun tests with coverage:
go test ./... -coverGenerate detailed coverage report:
go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.outThe test suite covers:
-
Helper Tests (
helper/helpers_test.go)- Context timeout functionality
- Context cancellation behavior
- Deadline verification
-
Model Tests (
model/*_test.go)- Task model validation
- Email model validation
- Filter model validation
- Status constants verification
-
Repository Tests (
repository/task_test.go)- Repository structure validation
- Type checking
- Note: Integration tests requiring MongoDB should be run separately
-
Handler Tests (
handler/task_test.go)- TaskService initialization
- Context management
- Business logic validation
Mock implementations are available for testing in repository/mocks/:
import "github.com/amiraliio/goSchedule/repository/mocks"
mockRepo := &mocks.MockTaskRepository{
ListFunc: func(ctx context.Context, filter *model.Filter) []*model.Task {
// Return test data
return testTasks
},
}For integration tests that require MongoDB:
- Set up a test MongoDB instance
- Configure test environment variables
- Run integration tests separately:
go test ./repository -tags=integration- Unit tests should not require external dependencies (database, email server)
- Use mock implementations for testing business logic
- Integration tests should be isolated and use test databases
- Always clean up test data after integration tests
app.go: Environment variable loadingdatabase.go: MongoDB connection management
task.go: Task processing business logic
helpers.go: Context timeout utilitiesmailhelper.go: Email sending functionalitymongohelper.go: MongoDB helper functions
task.go: Task data model and constantsmail.go: Email data modelfilter.go: Query filter model
app.go: Service initialization and dependency injection
task.go: Task data access implementationinterfaces/: Repository interfaces for dependency inversion
The project uses the following main dependencies:
- MongoDB Driver:
go.mongodb.org/mongo-driver v1.17.4- Latest stable MongoDB driver - Environment Configuration:
github.com/joho/godotenv v1.5.1- Environment variable management - Go Version: 1.21+ - Modern Go with latest features and performance improvements
All dependencies are kept up-to-date for security and performance. To update dependencies:
go get -u ./...
go mod tidy- Define interfaces in
repository/interfaces/ - Implement business logic in
handler/ - Add data models in
model/ - Implement repository in
repository/ - Wire up dependencies in
provider/ - Write unit tests for new functionality
- Update documentation
To run the scheduler periodically, set up a cron job:
# Run every 5 minutes
*/5 * * * * /path/to/goSchedule >> /path/to/logs/goSchedule.log 2>&1The application handles errors gracefully:
- Failed email sends are logged and tasks are marked as "Failed"
- MongoDB connection errors are logged with fatal status
- Context timeouts prevent long-running operations
Contributions are welcome! Please feel free to submit a Pull Request.
This project is open source and available under the MIT License.
Developed by amiraliio
For issues, questions, or contributions, please visit the GitHub repository.