feat: add tenant refresh functionality to HTTP API and job processing
CI / changes (push) Successful in 11s
CI / openapi (push) Has been skipped
CI / go (push) Successful in 59s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Has been skipped
CI / docker-bird (push) Has been skipped
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Has been skipped
CI / bird2 (push) Successful in 43s
CI / docker-go (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, , evobgp-all) (push) Has been skipped
CI / docker-go (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, , evobgp-api) (push) Has been skipped
CI / docker-go (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, , evobgp-deploy) (push) Has been skipped
CI / docker-go (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, , evobgp-ingest) (push) Has been skipped
CI / docker-go (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, , evobgp-node) (push) Has been skipped
CI / docker-go (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, , evobgp-render) (push) Has been skipped
CI / docker-go (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, , evobgp-scheduler) (push) Has been skipped
CI / docker-go-prime (push) Successful in 55s
CI / docker-go (deploy/docker/evobgp-agent/Dockerfile, , evobgp-agent) (push) Has been cancelled
CI / changes (push) Successful in 11s
CI / openapi (push) Has been skipped
CI / go (push) Successful in 59s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Has been skipped
CI / docker-bird (push) Has been skipped
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Has been skipped
CI / bird2 (push) Successful in 43s
CI / docker-go (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, , evobgp-all) (push) Has been skipped
CI / docker-go (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, , evobgp-api) (push) Has been skipped
CI / docker-go (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, , evobgp-deploy) (push) Has been skipped
CI / docker-go (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, , evobgp-ingest) (push) Has been skipped
CI / docker-go (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, , evobgp-node) (push) Has been skipped
CI / docker-go (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, , evobgp-render) (push) Has been skipped
CI / docker-go (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, , evobgp-scheduler) (push) Has been skipped
CI / docker-go-prime (push) Successful in 55s
CI / docker-go (deploy/docker/evobgp-agent/Dockerfile, , evobgp-agent) (push) Has been cancelled
Implemented a new endpoint for tenant refresh in the HTTP API, allowing for the refresh of modules associated with a tenant. Enhanced job processing to handle tenant refresh jobs, including logic for managing module IDs and job status updates. Updated the scheduler to enqueue tenant refresh jobs based on module due dates, improving the overall efficiency of module management. Additionally, introduced caching for ASN prefix data to optimize performance during refresh operations.
This commit is contained in:
+39
-34
@@ -1,8 +1,10 @@
|
||||
// Package scheduler drives module refresh intervals and enqueues module_refresh jobs on the shared Registry.
|
||||
// Package scheduler drives module refresh intervals and enqueues tenant_refresh jobs on the shared Registry.
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@@ -13,6 +15,7 @@ import (
|
||||
"evobgp/internal/broker"
|
||||
"evobgp/internal/config"
|
||||
"evobgp/internal/jobs"
|
||||
"evobgp/internal/pipeline"
|
||||
"evobgp/internal/store"
|
||||
)
|
||||
|
||||
@@ -39,9 +42,9 @@ func Run(ctx context.Context, deps *Deps) {
|
||||
t := time.NewTicker(30 * time.Second)
|
||||
defer t.Stop()
|
||||
if deps.Jobs != nil {
|
||||
log.Printf("evobgp-scheduler: active (in-process enqueue module_refresh)")
|
||||
log.Printf("evobgp-scheduler: active (in-process enqueue tenant_refresh)")
|
||||
} else {
|
||||
log.Printf("evobgp-scheduler: active (HTTP POST .../modules/{id}/refresh → %s)", strings.TrimSpace(deps.APIBase))
|
||||
log.Printf("evobgp-scheduler: active (HTTP POST .../tenant/refresh → %s)", strings.TrimSpace(deps.APIBase))
|
||||
}
|
||||
for {
|
||||
select {
|
||||
@@ -60,51 +63,53 @@ func tick(ctx context.Context, deps *Deps) {
|
||||
log.Printf("evobgp-scheduler: list tenants: %v", err)
|
||||
return
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
tickBucket := now.Unix() / pipeline.SchedulerTickSec
|
||||
for _, tid := range tenants {
|
||||
var due []string
|
||||
for _, mod := range deps.Store.ListModules(tid) {
|
||||
if !mod.Enabled || mod.Type == "IP_RANGES" {
|
||||
if pipeline.ModuleDueForScheduler(mod, now) {
|
||||
due = append(due, mod.ID)
|
||||
}
|
||||
}
|
||||
if len(due) == 0 {
|
||||
continue
|
||||
}
|
||||
key := fmt.Sprintf("sched-tenant-%s-%d", tid, tickBucket)
|
||||
if deps.Jobs != nil {
|
||||
ids := append([]string(nil), due...)
|
||||
_, created, err := deps.Jobs.Enqueue(tid, jobs.KindTenantRefresh, &key, nil, map[string]any{
|
||||
"module_ids": ids,
|
||||
"trigger": "scheduler",
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("evobgp-scheduler: enqueue tenant %s: %v", tid, err)
|
||||
continue
|
||||
}
|
||||
interval := mod.RefreshIntervalSec
|
||||
if interval <= 0 {
|
||||
continue
|
||||
}
|
||||
win := interval
|
||||
if win < 60 {
|
||||
win = 60
|
||||
}
|
||||
bucket := time.Now().Unix() / int64(win)
|
||||
key := fmt.Sprintf("sched-%s-%d", mod.ID, bucket)
|
||||
if deps.Jobs != nil {
|
||||
mid := mod.ID
|
||||
_, created, err := deps.Jobs.Enqueue(tid, jobs.KindModuleRefresh, &key, &mid, map[string]any{
|
||||
"module_id": mod.ID,
|
||||
"trigger": "scheduler",
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("evobgp-scheduler: enqueue module %s: %v", mod.ID, err)
|
||||
continue
|
||||
}
|
||||
if created {
|
||||
log.Printf("evobgp-scheduler: queued refresh for module %s (%s)", mod.ID, mod.Type)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := postModuleRefresh(ctx, deps, mod.ID, key); err != nil {
|
||||
log.Printf("evobgp-scheduler: http refresh module %s: %v", mod.ID, err)
|
||||
if created {
|
||||
log.Printf("evobgp-scheduler: queued tenant refresh for %d module(s) in tenant %s", len(due), tid)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := postTenantRefresh(ctx, deps, due, key); err != nil {
|
||||
log.Printf("evobgp-scheduler: http tenant refresh %s: %v", tid, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func postModuleRefresh(ctx context.Context, deps *Deps, moduleID, idempotencyKey string) error {
|
||||
func postTenantRefresh(ctx context.Context, deps *Deps, moduleIDs []string, idempotencyKey string) error {
|
||||
base := strings.TrimRight(strings.TrimSpace(deps.APIBase), "/")
|
||||
u := base + "/v1/modules/" + moduleID + "/refresh"
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, nil)
|
||||
u := base + "/v1/tenant/refresh"
|
||||
body, err := json.Marshal(map[string]any{"module_ids": moduleIDs})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+strings.TrimSpace(deps.APIToken))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
if idempotencyKey != "" {
|
||||
req.Header.Set("Idempotency-Key", idempotencyKey)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user