2021-09-18 17:55:59 +05:30
|
|
|
package asynqmon
|
2020-11-24 06:54:00 -08:00
|
|
|
|
|
|
|
|
import (
|
2021-10-03 07:20:00 +05:30
|
|
|
"fmt"
|
2021-09-30 23:58:45 +05:30
|
|
|
"net/http"
|
|
|
|
|
|
2021-09-30 23:56:01 +05:30
|
|
|
"github.com/go-redis/redis/v8"
|
2020-11-24 06:54:00 -08:00
|
|
|
"github.com/gorilla/mux"
|
2021-09-18 19:53:42 +05:30
|
|
|
|
2020-11-24 06:54:00 -08:00
|
|
|
"github.com/hibiken/asynq"
|
2021-01-08 07:16:48 -08:00
|
|
|
)
|
|
|
|
|
|
2021-10-03 07:20:00 +05:30
|
|
|
// MiddlewareFunc helps chain http.Handler(s).
|
|
|
|
|
type MiddlewareFunc func(http.Handler) http.Handler
|
|
|
|
|
|
2021-10-04 20:54:37 +05:30
|
|
|
// Options can be used to customise HTTPHandler.
|
2021-10-04 00:00:40 +05:30
|
|
|
type Options struct {
|
2021-10-03 07:20:00 +05:30
|
|
|
RedisConnOpt asynq.RedisConnOpt
|
|
|
|
|
Middlewares []MiddlewareFunc
|
2021-10-02 12:57:41 +05:30
|
|
|
PayloadFormatter PayloadFormatter
|
2021-09-30 23:53:01 +05:30
|
|
|
StaticContentHandler http.Handler
|
2021-04-23 22:58:32 -04:00
|
|
|
}
|
|
|
|
|
|
2021-10-04 20:54:37 +05:30
|
|
|
// HTTPHandler can serve the API and UI required for asynq monitoring.
|
2021-10-04 00:00:40 +05:30
|
|
|
type HTTPHandler struct {
|
2021-10-03 07:20:00 +05:30
|
|
|
router *mux.Router
|
|
|
|
|
closers []func() error
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-04 20:54:37 +05:30
|
|
|
// ServeHTTP will serve the API request as well as any static resources.
|
2021-10-04 00:00:40 +05:30
|
|
|
func (a *HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
2021-10-03 07:20:00 +05:30
|
|
|
a.router.ServeHTTP(w, r)
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-04 20:54:37 +05:30
|
|
|
// New creates an HTTPHandler that can be used to serve asynqmon web API with static contents.
|
2021-10-04 20:48:00 +05:30
|
|
|
func New(opts Options) *HTTPHandler {
|
2021-10-03 07:20:00 +05:30
|
|
|
rc, ok := opts.RedisConnOpt.MakeRedisClient().(redis.UniversalClient)
|
|
|
|
|
if !ok {
|
2021-10-04 00:00:40 +05:30
|
|
|
panic(fmt.Sprintf("asnyqmon.HTTPHandler: unsupported RedisConnOpt type %T", opts.RedisConnOpt))
|
2021-10-03 07:20:00 +05:30
|
|
|
}
|
|
|
|
|
i := asynq.NewInspector(opts.RedisConnOpt)
|
2021-10-04 00:00:40 +05:30
|
|
|
return &HTTPHandler{router: muxRouter(opts, rc, i), closers: []func() error{rc.Close, i.Close}}
|
2021-10-03 07:20:00 +05:30
|
|
|
}
|
|
|
|
|
|
2021-10-04 20:54:37 +05:30
|
|
|
// Close will close connections to redis.
|
2021-10-04 00:00:40 +05:30
|
|
|
func (a *HTTPHandler) Close() error {
|
2021-10-03 07:20:00 +05:30
|
|
|
for _, f := range a.closers {
|
|
|
|
|
if err := f(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-04 00:00:40 +05:30
|
|
|
func muxRouter(opts Options, rc redis.UniversalClient, inspector *asynq.Inspector) *mux.Router {
|
2021-09-18 17:55:59 +05:30
|
|
|
router := mux.NewRouter()
|
2021-10-01 00:19:41 +05:30
|
|
|
|
2021-10-02 12:57:41 +05:30
|
|
|
var pf PayloadFormatter = defaultPayloadFormatter
|
|
|
|
|
if opts.PayloadFormatter != nil {
|
|
|
|
|
pf = opts.PayloadFormatter
|
2021-09-18 17:56:00 +05:30
|
|
|
}
|
2020-11-24 06:54:00 -08:00
|
|
|
|
2021-09-18 17:55:59 +05:30
|
|
|
for _, mf := range opts.Middlewares {
|
2021-10-03 07:20:00 +05:30
|
|
|
router.Use(mux.MiddlewareFunc(mf))
|
2021-09-06 06:32:23 -07:00
|
|
|
}
|
2020-11-24 06:54:00 -08:00
|
|
|
|
|
|
|
|
api := router.PathPrefix("/api").Subrouter()
|
2020-12-06 08:46:14 -08:00
|
|
|
// Queue endpoints.
|
2021-10-02 12:57:41 +05:30
|
|
|
api.HandleFunc("/queues", newListQueuesHandlerFunc(inspector)).Methods("GET")
|
2021-10-01 00:19:41 +05:30
|
|
|
api.HandleFunc("/queues/{qname}", newGetQueueHandlerFunc(inspector)).Methods("GET")
|
|
|
|
|
api.HandleFunc("/queues/{qname}", newDeleteQueueHandlerFunc(inspector)).Methods("DELETE")
|
2020-12-07 06:41:16 -08:00
|
|
|
api.HandleFunc("/queues/{qname}:pause", newPauseQueueHandlerFunc(inspector)).Methods("POST")
|
|
|
|
|
api.HandleFunc("/queues/{qname}:resume", newResumeQueueHandlerFunc(inspector)).Methods("POST")
|
2020-12-06 08:46:14 -08:00
|
|
|
|
2020-12-27 15:45:54 -08:00
|
|
|
// Queue Historical Stats endpoint.
|
2021-10-01 00:19:41 +05:30
|
|
|
api.HandleFunc("/queue_stats", newListQueueStatsHandlerFunc(inspector)).Methods("GET")
|
2020-12-27 15:45:54 -08:00
|
|
|
|
2020-12-06 08:46:14 -08:00
|
|
|
// Task endpoints.
|
2021-10-02 12:57:41 +05:30
|
|
|
api.HandleFunc("/queues/{qname}/active_tasks", newListActiveTasksHandlerFunc(inspector, pf)).Methods("GET")
|
2020-12-07 06:41:16 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/active_tasks/{task_id}:cancel", newCancelActiveTaskHandlerFunc(inspector)).Methods("POST")
|
2020-12-23 06:59:44 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/active_tasks:cancel_all", newCancelAllActiveTasksHandlerFunc(inspector)).Methods("POST")
|
2020-12-23 06:23:15 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/active_tasks:batch_cancel", newBatchCancelActiveTasksHandlerFunc(inspector)).Methods("POST")
|
2021-01-20 21:30:27 -08:00
|
|
|
|
2021-10-02 12:57:41 +05:30
|
|
|
api.HandleFunc("/queues/{qname}/pending_tasks", newListPendingTasksHandlerFunc(inspector, pf)).Methods("GET")
|
2021-05-28 14:40:09 -07:00
|
|
|
api.HandleFunc("/queues/{qname}/pending_tasks/{task_id}", newDeleteTaskHandlerFunc(inspector)).Methods("DELETE")
|
2021-01-20 21:30:27 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/pending_tasks:delete_all", newDeleteAllPendingTasksHandlerFunc(inspector)).Methods("DELETE")
|
|
|
|
|
api.HandleFunc("/queues/{qname}/pending_tasks:batch_delete", newBatchDeleteTasksHandlerFunc(inspector)).Methods("POST")
|
2021-05-28 14:40:09 -07:00
|
|
|
api.HandleFunc("/queues/{qname}/pending_tasks/{task_id}:archive", newArchiveTaskHandlerFunc(inspector)).Methods("POST")
|
2021-01-20 21:30:27 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/pending_tasks:archive_all", newArchiveAllPendingTasksHandlerFunc(inspector)).Methods("POST")
|
|
|
|
|
api.HandleFunc("/queues/{qname}/pending_tasks:batch_archive", newBatchArchiveTasksHandlerFunc(inspector)).Methods("POST")
|
|
|
|
|
|
2021-10-02 12:57:41 +05:30
|
|
|
api.HandleFunc("/queues/{qname}/scheduled_tasks", newListScheduledTasksHandlerFunc(inspector, pf)).Methods("GET")
|
2021-05-28 14:40:09 -07:00
|
|
|
api.HandleFunc("/queues/{qname}/scheduled_tasks/{task_id}", newDeleteTaskHandlerFunc(inspector)).Methods("DELETE")
|
2020-12-07 07:22:04 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/scheduled_tasks:delete_all", newDeleteAllScheduledTasksHandlerFunc(inspector)).Methods("DELETE")
|
2020-12-17 16:05:22 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/scheduled_tasks:batch_delete", newBatchDeleteTasksHandlerFunc(inspector)).Methods("POST")
|
2021-05-28 14:40:09 -07:00
|
|
|
api.HandleFunc("/queues/{qname}/scheduled_tasks/{task_id}:run", newRunTaskHandlerFunc(inspector)).Methods("POST")
|
2020-12-19 06:07:23 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/scheduled_tasks:run_all", newRunAllScheduledTasksHandlerFunc(inspector)).Methods("POST")
|
2020-12-15 06:16:58 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/scheduled_tasks:batch_run", newBatchRunTasksHandlerFunc(inspector)).Methods("POST")
|
2021-05-28 14:40:09 -07:00
|
|
|
api.HandleFunc("/queues/{qname}/scheduled_tasks/{task_id}:archive", newArchiveTaskHandlerFunc(inspector)).Methods("POST")
|
2021-01-12 11:59:44 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/scheduled_tasks:archive_all", newArchiveAllScheduledTasksHandlerFunc(inspector)).Methods("POST")
|
|
|
|
|
api.HandleFunc("/queues/{qname}/scheduled_tasks:batch_archive", newBatchArchiveTasksHandlerFunc(inspector)).Methods("POST")
|
2021-01-20 21:30:27 -08:00
|
|
|
|
2021-10-02 12:57:41 +05:30
|
|
|
api.HandleFunc("/queues/{qname}/retry_tasks", newListRetryTasksHandlerFunc(inspector, pf)).Methods("GET")
|
2021-05-28 14:40:09 -07:00
|
|
|
api.HandleFunc("/queues/{qname}/retry_tasks/{task_id}", newDeleteTaskHandlerFunc(inspector)).Methods("DELETE")
|
2020-12-07 07:22:04 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/retry_tasks:delete_all", newDeleteAllRetryTasksHandlerFunc(inspector)).Methods("DELETE")
|
2020-12-17 16:05:22 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/retry_tasks:batch_delete", newBatchDeleteTasksHandlerFunc(inspector)).Methods("POST")
|
2021-05-28 14:40:09 -07:00
|
|
|
api.HandleFunc("/queues/{qname}/retry_tasks/{task_id}:run", newRunTaskHandlerFunc(inspector)).Methods("POST")
|
2020-12-19 06:07:23 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/retry_tasks:run_all", newRunAllRetryTasksHandlerFunc(inspector)).Methods("POST")
|
2020-12-15 06:16:58 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/retry_tasks:batch_run", newBatchRunTasksHandlerFunc(inspector)).Methods("POST")
|
2021-05-28 14:40:09 -07:00
|
|
|
api.HandleFunc("/queues/{qname}/retry_tasks/{task_id}:archive", newArchiveTaskHandlerFunc(inspector)).Methods("POST")
|
2021-01-12 11:59:44 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/retry_tasks:archive_all", newArchiveAllRetryTasksHandlerFunc(inspector)).Methods("POST")
|
|
|
|
|
api.HandleFunc("/queues/{qname}/retry_tasks:batch_archive", newBatchArchiveTasksHandlerFunc(inspector)).Methods("POST")
|
2021-01-20 21:30:27 -08:00
|
|
|
|
2021-10-02 12:57:41 +05:30
|
|
|
api.HandleFunc("/queues/{qname}/archived_tasks", newListArchivedTasksHandlerFunc(inspector, pf)).Methods("GET")
|
2021-05-28 14:40:09 -07:00
|
|
|
api.HandleFunc("/queues/{qname}/archived_tasks/{task_id}", newDeleteTaskHandlerFunc(inspector)).Methods("DELETE")
|
2021-01-12 11:59:44 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/archived_tasks:delete_all", newDeleteAllArchivedTasksHandlerFunc(inspector)).Methods("DELETE")
|
|
|
|
|
api.HandleFunc("/queues/{qname}/archived_tasks:batch_delete", newBatchDeleteTasksHandlerFunc(inspector)).Methods("POST")
|
2021-05-28 14:40:09 -07:00
|
|
|
api.HandleFunc("/queues/{qname}/archived_tasks/{task_id}:run", newRunTaskHandlerFunc(inspector)).Methods("POST")
|
2021-01-12 11:59:44 -08:00
|
|
|
api.HandleFunc("/queues/{qname}/archived_tasks:run_all", newRunAllArchivedTasksHandlerFunc(inspector)).Methods("POST")
|
|
|
|
|
api.HandleFunc("/queues/{qname}/archived_tasks:batch_run", newBatchRunTasksHandlerFunc(inspector)).Methods("POST")
|
2020-12-06 08:46:14 -08:00
|
|
|
|
2021-10-02 12:57:41 +05:30
|
|
|
api.HandleFunc("/queues/{qname}/tasks/{task_id}", newGetTaskHandlerFunc(inspector, pf)).Methods("GET")
|
2021-07-30 05:53:14 -07:00
|
|
|
|
2020-12-30 08:58:50 -08:00
|
|
|
// Servers endpoints.
|
2021-10-02 12:57:41 +05:30
|
|
|
api.HandleFunc("/servers", newListServersHandlerFunc(inspector, pf)).Methods("GET")
|
2020-12-30 08:58:50 -08:00
|
|
|
|
2020-12-06 08:46:14 -08:00
|
|
|
// Scheduler Entry endpoints.
|
2021-10-02 12:57:41 +05:30
|
|
|
api.HandleFunc("/scheduler_entries", newListSchedulerEntriesHandlerFunc(inspector, pf)).Methods("GET")
|
2021-10-01 00:19:41 +05:30
|
|
|
api.HandleFunc("/scheduler_entries/{entry_id}/enqueue_events", newListSchedulerEnqueueEventsHandlerFunc(inspector)).Methods("GET")
|
2020-11-24 06:54:00 -08:00
|
|
|
|
2021-01-03 06:56:53 -08:00
|
|
|
// Redis info endpoint.
|
2021-10-03 07:20:00 +05:30
|
|
|
switch c := rc.(type) {
|
2021-09-18 17:55:59 +05:30
|
|
|
case *redis.ClusterClient:
|
|
|
|
|
api.HandleFunc("/redis_info", newRedisClusterInfoHandlerFunc(c, inspector)).Methods("GET")
|
|
|
|
|
case *redis.Client:
|
|
|
|
|
api.HandleFunc("/redis_info", newRedisInfoHandlerFunc(c)).Methods("GET")
|
2020-11-24 06:54:00 -08:00
|
|
|
}
|
|
|
|
|
|
2021-10-01 00:19:41 +05:30
|
|
|
router.PathPrefix("/").Handler(opts.StaticContentHandler)
|
2021-09-18 17:55:59 +05:30
|
|
|
return router
|
2020-11-24 06:54:00 -08:00
|
|
|
}
|