92 lines
2.4 KiB
Markdown
92 lines
2.4 KiB
Markdown
# Fetcher Job Scheduler
|
|
|
|
This project demonstrates a lightweight job runner where each job defines its own execution interval directly in its source file.
|
|
|
|
## Structure
|
|
|
|
- `main.go` wires signal handling and starts the scheduler.
|
|
- `internal/scheduler` contains the runner implementation that executes jobs on their declared cadence.
|
|
- `jobs` hosts job definitions; each job registers itself during package initialization.
|
|
|
|
## Running
|
|
|
|
```bash
|
|
go run .
|
|
```
|
|
|
|
You should see the example job print a timestamp about every five seconds.
|
|
|
|
The scheduler will also start the clan monitor job once all required environment variables are present.
|
|
|
|
## Creating a Job
|
|
|
|
1. Add a new file under `jobs`, for example `jobs/fetch_users.go`.
|
|
2. Declare any interval value in that file (e.g., `const fetchInterval = 10 * time.Second`).
|
|
3. Implement the `jobs.Job` interface and call `Register` in an `init` function.
|
|
|
|
```go
|
|
package jobs
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
)
|
|
|
|
const fetchInterval = 10 * time.Second
|
|
|
|
func init() {
|
|
Register(&FetchUsersJob{})
|
|
}
|
|
|
|
type FetchUsersJob struct{}
|
|
|
|
func (FetchUsersJob) Name() string { return "fetch_users" }
|
|
func (FetchUsersJob) Interval() time.Duration { return fetchInterval }
|
|
|
|
func (FetchUsersJob) Run(ctx context.Context) error {
|
|
// Perform work here.
|
|
return nil
|
|
}
|
|
```
|
|
|
|
The scheduler automatically discovers and runs the new job without additional wiring.
|
|
|
|
## Clan Monitor Job
|
|
|
|
The `clan_monitor` job checks your Clash of Clans clan members and sends a Discord DM when someone has been offline for at least two days. The job runs every 30 minutes and requires the following environment variables:
|
|
|
|
- `COC_API_TOKEN`: Clash of Clans developer API token.
|
|
- `COC_CLAN_TAG`: Clan tag (include the leading `#`, e.g. `#123ABC`).
|
|
- `DISCORD_BOT_TOKEN`: Discord bot token with permission to create DMs.
|
|
- `DISCORD_RECIPIENT_ID`: Your Discord user ID to receive notifications.
|
|
|
|
Example invocation:
|
|
|
|
```bash
|
|
export COC_API_TOKEN="..."
|
|
export COC_CLAN_TAG="#123ABC"
|
|
export DISCORD_BOT_TOKEN="..."
|
|
export DISCORD_RECIPIENT_ID="1234567890"
|
|
go run .
|
|
```
|
|
|
|
If any value is missing, the job logs `clan monitor job disabled: <reason>` during startup and will not register.
|
|
|
|
## Docker Image
|
|
|
|
Build the container image:
|
|
|
|
```bash
|
|
docker build -t fetcher .
|
|
```
|
|
|
|
Run with the required environment variables:
|
|
|
|
```bash
|
|
docker run --rm \
|
|
-e COC_API_TOKEN="..." \
|
|
-e COC_CLAN_TAG="#123ABC" \
|
|
-e DISCORD_BOT_TOKEN="..." \
|
|
-e DISCORD_RECIPIENT_ID="1234567890" \
|
|
fetcher
|
|
```
|