add(crm): api spec for workflow jobs
This commit is contained in:
parent
101c322299
commit
73728bcf61
@ -91,7 +91,7 @@
|
||||
"name": "get",
|
||||
"method": "GET",
|
||||
"path": "/{workflowID}",
|
||||
"title": "Get existing workflow details",
|
||||
"title": "Get workflow details",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
@ -163,6 +163,188 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Jobs",
|
||||
"description": "Workflow Jobs",
|
||||
"package": "crm",
|
||||
"entrypoint": "job",
|
||||
"path": "/job",
|
||||
"authentication": [],
|
||||
"struct": [
|
||||
{
|
||||
"imports": [
|
||||
"github.com/crusttech/crust/crm/types",
|
||||
"sqlxTypes github.com/jmoiron/sqlx/types"
|
||||
]
|
||||
}
|
||||
],
|
||||
"apis": [
|
||||
{
|
||||
"name": "list",
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"title": "List jobs",
|
||||
"parameters": {
|
||||
"get": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "status",
|
||||
"required": false,
|
||||
"title": "Job status (`ok`, `error`, `running`, `cancelled` or `queued`)"
|
||||
},
|
||||
{
|
||||
"name": "page",
|
||||
"type": "int",
|
||||
"required": false,
|
||||
"title": "Page number (0 based)"
|
||||
},
|
||||
{
|
||||
"name": "perPage",
|
||||
"type": "int",
|
||||
"required": false,
|
||||
"title": "Returned items per page (default 50)"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "run",
|
||||
"path": "/",
|
||||
"method": "POST",
|
||||
"title": "Create a new job",
|
||||
"parameters": {
|
||||
"post": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "workflowID",
|
||||
"required": true,
|
||||
"title": "Workflow ID"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "startAt",
|
||||
"required": false,
|
||||
"title": "Start datetime for a delayed job"
|
||||
},
|
||||
{
|
||||
"type": "types.JobParameterSet",
|
||||
"name": "parameters",
|
||||
"required": false,
|
||||
"title": "Extra job parameters (map[string]string)"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "get",
|
||||
"method": "GET",
|
||||
"path": "/{jobID}",
|
||||
"title": "Get job details",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "jobID",
|
||||
"required": true,
|
||||
"title": "Job ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "logs",
|
||||
"method": "GET",
|
||||
"path": "/{jobID}/logs",
|
||||
"title": "Get job logs",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "jobID",
|
||||
"required": true,
|
||||
"title": "Job ID"
|
||||
},
|
||||
{
|
||||
"name": "page",
|
||||
"type": "int",
|
||||
"required": false,
|
||||
"title": "Page number (0 based)"
|
||||
},
|
||||
{
|
||||
"name": "perPage",
|
||||
"type": "int",
|
||||
"required": false,
|
||||
"title": "Returned items per page (default 50)"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "update",
|
||||
"method": "POST",
|
||||
"path": "/{jobID}",
|
||||
"title": "Update job details",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "jobID",
|
||||
"required": true,
|
||||
"title": "Job ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "status",
|
||||
"required": false,
|
||||
"title": "Job status (`ok`, `error`, `running`, `cancelled` or `queued`)"
|
||||
},
|
||||
{
|
||||
"type": "sqlxTypes.JSONText",
|
||||
"name": "log",
|
||||
"required": false,
|
||||
"title": "Job log item (append-only)"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "workflowID",
|
||||
"required": false,
|
||||
"title": "Workflow ID"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "startAt",
|
||||
"required": false,
|
||||
"title": "Start datetime for a delayed job"
|
||||
},
|
||||
{
|
||||
"type": "types.JobParameterSet",
|
||||
"name": "parameters",
|
||||
"required": false,
|
||||
"title": "Extra job parameters (map[string]string)"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "delete",
|
||||
"method": "DELETE",
|
||||
"path": "/{jobID}",
|
||||
"title": "Cancel job",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "jobID",
|
||||
"required": true,
|
||||
"title": "Job ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Pages",
|
||||
"description": "CRM module pages",
|
||||
|
||||
184
api/crm/spec/job.json
Normal file
184
api/crm/spec/job.json
Normal file
@ -0,0 +1,184 @@
|
||||
{
|
||||
"Title": "Jobs",
|
||||
"Description": "Workflow Jobs",
|
||||
"Package": "crm",
|
||||
"Interface": "Job",
|
||||
"Struct": [
|
||||
{
|
||||
"imports": [
|
||||
"github.com/crusttech/crust/crm/types",
|
||||
"sqlxTypes github.com/jmoiron/sqlx/types"
|
||||
]
|
||||
}
|
||||
],
|
||||
"Parameters": null,
|
||||
"Protocol": "",
|
||||
"Authentication": [],
|
||||
"Path": "/job",
|
||||
"APIs": [
|
||||
{
|
||||
"Name": "list",
|
||||
"Method": "GET",
|
||||
"Title": "List jobs",
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"get": [
|
||||
{
|
||||
"name": "status",
|
||||
"required": false,
|
||||
"title": "Job status (`ok`, `error`, `running`, `cancelled` or `queued`)",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "page",
|
||||
"required": false,
|
||||
"title": "Page number (0 based)",
|
||||
"type": "int"
|
||||
},
|
||||
{
|
||||
"name": "perPage",
|
||||
"required": false,
|
||||
"title": "Returned items per page (default 50)",
|
||||
"type": "int"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "run",
|
||||
"Method": "POST",
|
||||
"Title": "Create a new job",
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"post": [
|
||||
{
|
||||
"name": "workflowID",
|
||||
"required": true,
|
||||
"title": "Workflow ID",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "startAt",
|
||||
"required": false,
|
||||
"title": "Start datetime for a delayed job",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "parameters",
|
||||
"required": false,
|
||||
"title": "Extra job parameters (map[string]string)",
|
||||
"type": "types.JobParameterSet"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "get",
|
||||
"Method": "GET",
|
||||
"Title": "Get job details",
|
||||
"Path": "/{jobID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "jobID",
|
||||
"required": true,
|
||||
"title": "Job ID",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "logs",
|
||||
"Method": "GET",
|
||||
"Title": "Get job logs",
|
||||
"Path": "/{jobID}/logs",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "jobID",
|
||||
"required": true,
|
||||
"title": "Job ID",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "page",
|
||||
"required": false,
|
||||
"title": "Page number (0 based)",
|
||||
"type": "int"
|
||||
},
|
||||
{
|
||||
"name": "perPage",
|
||||
"required": false,
|
||||
"title": "Returned items per page (default 50)",
|
||||
"type": "int"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "update",
|
||||
"Method": "POST",
|
||||
"Title": "Update job details",
|
||||
"Path": "/{jobID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "jobID",
|
||||
"required": true,
|
||||
"title": "Job ID",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
{
|
||||
"name": "status",
|
||||
"required": false,
|
||||
"title": "Job status (`ok`, `error`, `running`, `cancelled` or `queued`)",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "log",
|
||||
"required": false,
|
||||
"title": "Job log item (append-only)",
|
||||
"type": "sqlxTypes.JSONText"
|
||||
},
|
||||
{
|
||||
"name": "workflowID",
|
||||
"required": false,
|
||||
"title": "Workflow ID",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "startAt",
|
||||
"required": false,
|
||||
"title": "Start datetime for a delayed job",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "parameters",
|
||||
"required": false,
|
||||
"title": "Extra job parameters (map[string]string)",
|
||||
"type": "types.JobParameterSet"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "delete",
|
||||
"Method": "DELETE",
|
||||
"Title": "Cancel job",
|
||||
"Path": "/{jobID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "jobID",
|
||||
"required": true,
|
||||
"title": "Job ID",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -59,7 +59,7 @@
|
||||
{
|
||||
"Name": "get",
|
||||
"Method": "GET",
|
||||
"Title": "Get existing workflow details",
|
||||
"Title": "Get workflow details",
|
||||
"Path": "/{workflowID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
|
||||
29
crm/repository/job.go
Normal file
29
crm/repository/job.go
Normal file
@ -0,0 +1,29 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
_ "github.com/crusttech/crust/crm/types"
|
||||
)
|
||||
|
||||
type (
|
||||
JobRepository interface {
|
||||
With(ctx context.Context, db *factory.DB) JobRepository
|
||||
}
|
||||
|
||||
job struct {
|
||||
*repository
|
||||
}
|
||||
)
|
||||
|
||||
func Job(ctx context.Context, db *factory.DB) JobRepository {
|
||||
return (&job{}).With(ctx, db)
|
||||
}
|
||||
|
||||
func (r *job) With(ctx context.Context, db *factory.DB) JobRepository {
|
||||
return &job{
|
||||
repository: r.repository.With(ctx, db),
|
||||
}
|
||||
}
|
||||
107
crm/rest/handlers/job.go
Normal file
107
crm/rest/handlers/job.go
Normal file
@ -0,0 +1,107 @@
|
||||
package handlers
|
||||
|
||||
/*
|
||||
Hello! This file is auto-generated from `docs/src/spec.json`.
|
||||
|
||||
For development:
|
||||
In order to update the generated files, edit this file under the location,
|
||||
add your struct fields, imports, API definitions and whatever you want, and:
|
||||
|
||||
1. run [spec](https://github.com/titpetric/spec) in the same folder,
|
||||
2. run `./_gen.php` in this folder.
|
||||
|
||||
You may edit `job.go`, `job.util.go` or `job_test.go` to
|
||||
implement your API calls, helper functions and tests. The file `job.go`
|
||||
is only generated the first time, and will not be overwritten if it exists.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/go-chi/chi"
|
||||
"net/http"
|
||||
|
||||
"github.com/titpetric/factory/resputil"
|
||||
|
||||
"github.com/crusttech/crust/crm/rest/request"
|
||||
)
|
||||
|
||||
// Internal API interface
|
||||
type JobAPI interface {
|
||||
List(context.Context, *request.JobList) (interface{}, error)
|
||||
Run(context.Context, *request.JobRun) (interface{}, error)
|
||||
Get(context.Context, *request.JobGet) (interface{}, error)
|
||||
Logs(context.Context, *request.JobLogs) (interface{}, error)
|
||||
Update(context.Context, *request.JobUpdate) (interface{}, error)
|
||||
Delete(context.Context, *request.JobDelete) (interface{}, error)
|
||||
}
|
||||
|
||||
// HTTP API interface
|
||||
type Job struct {
|
||||
List func(http.ResponseWriter, *http.Request)
|
||||
Run func(http.ResponseWriter, *http.Request)
|
||||
Get func(http.ResponseWriter, *http.Request)
|
||||
Logs func(http.ResponseWriter, *http.Request)
|
||||
Update func(http.ResponseWriter, *http.Request)
|
||||
Delete func(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
func NewJob(jh JobAPI) *Job {
|
||||
return &Job{
|
||||
List: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewJobList()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return jh.List(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Run: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewJobRun()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return jh.Run(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Get: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewJobGet()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return jh.Get(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Logs: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewJobLogs()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return jh.Logs(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Update: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewJobUpdate()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return jh.Update(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Delete: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewJobDelete()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return jh.Delete(r.Context(), params)
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (jh *Job) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(middlewares...)
|
||||
r.Route("/job", func(r chi.Router) {
|
||||
r.Get("/", jh.List)
|
||||
r.Post("/", jh.Run)
|
||||
r.Get("/{jobID}", jh.Get)
|
||||
r.Get("/{jobID}/logs", jh.Logs)
|
||||
r.Post("/{jobID}", jh.Update)
|
||||
r.Delete("/{jobID}", jh.Delete)
|
||||
})
|
||||
})
|
||||
}
|
||||
46
crm/rest/job.go
Normal file
46
crm/rest/job.go
Normal file
@ -0,0 +1,46 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/crusttech/crust/crm/rest/request"
|
||||
"github.com/crusttech/crust/crm/service"
|
||||
)
|
||||
|
||||
var _ = errors.Wrap
|
||||
|
||||
type (
|
||||
Job struct {
|
||||
job service.JobService
|
||||
}
|
||||
)
|
||||
|
||||
func (Job) New(jobSvc service.JobService) *Job {
|
||||
return &Job{jobSvc}
|
||||
}
|
||||
|
||||
func (ctrl *Job) List(ctx context.Context, r *request.JobList) (interface{}, error) {
|
||||
return nil, errors.New("Not implemented: Job.list")
|
||||
}
|
||||
|
||||
func (ctrl *Job) Run(ctx context.Context, r *request.JobRun) (interface{}, error) {
|
||||
return nil, errors.New("Not implemented: Job.run")
|
||||
}
|
||||
|
||||
func (ctrl *Job) Get(ctx context.Context, r *request.JobGet) (interface{}, error) {
|
||||
return nil, errors.New("Not implemented: Job.get")
|
||||
}
|
||||
|
||||
func (ctrl *Job) Logs(ctx context.Context, r *request.JobLogs) (interface{}, error) {
|
||||
return nil, errors.New("Not implemented: Job.logs")
|
||||
}
|
||||
|
||||
func (ctrl *Job) Update(ctx context.Context, r *request.JobUpdate) (interface{}, error) {
|
||||
return nil, errors.New("Not implemented: Job.update")
|
||||
}
|
||||
|
||||
func (ctrl *Job) Delete(ctx context.Context, r *request.JobDelete) (interface{}, error) {
|
||||
return nil, errors.New("Not implemented: Job.delete")
|
||||
}
|
||||
340
crm/rest/request/job.go
Normal file
340
crm/rest/request/job.go
Normal file
@ -0,0 +1,340 @@
|
||||
package request
|
||||
|
||||
/*
|
||||
Hello! This file is auto-generated from `docs/src/spec.json`.
|
||||
|
||||
For development:
|
||||
In order to update the generated files, edit this file under the location,
|
||||
add your struct fields, imports, API definitions and whatever you want, and:
|
||||
|
||||
1. run [spec](https://github.com/titpetric/spec) in the same folder,
|
||||
2. run `./_gen.php` in this folder.
|
||||
|
||||
You may edit `job.go`, `job.util.go` or `job_test.go` to
|
||||
implement your API calls, helper functions and tests. The file `job.go`
|
||||
is only generated the first time, and will not be overwritten if it exists.
|
||||
*/
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/crusttech/crust/crm/types"
|
||||
sqlxTypes "github.com/jmoiron/sqlx/types"
|
||||
)
|
||||
|
||||
var _ = chi.URLParam
|
||||
var _ = multipart.FileHeader{}
|
||||
|
||||
// Job list request parameters
|
||||
type JobList struct {
|
||||
Status string
|
||||
Page int
|
||||
PerPage int
|
||||
}
|
||||
|
||||
func NewJobList() *JobList {
|
||||
return &JobList{}
|
||||
}
|
||||
|
||||
func (j *JobList) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(j)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
if val, ok := get["status"]; ok {
|
||||
|
||||
j.Status = val
|
||||
}
|
||||
if val, ok := get["page"]; ok {
|
||||
|
||||
j.Page = parseInt(val)
|
||||
}
|
||||
if val, ok := get["perPage"]; ok {
|
||||
|
||||
j.PerPage = parseInt(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewJobList()
|
||||
|
||||
// Job run request parameters
|
||||
type JobRun struct {
|
||||
WorkflowID string
|
||||
StartAt string
|
||||
Parameters types.JobParameterSet
|
||||
}
|
||||
|
||||
func NewJobRun() *JobRun {
|
||||
return &JobRun{}
|
||||
}
|
||||
|
||||
func (j *JobRun) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(j)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
if val, ok := post["workflowID"]; ok {
|
||||
|
||||
j.WorkflowID = val
|
||||
}
|
||||
if val, ok := post["startAt"]; ok {
|
||||
|
||||
j.StartAt = val
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewJobRun()
|
||||
|
||||
// Job get request parameters
|
||||
type JobGet struct {
|
||||
JobID string
|
||||
}
|
||||
|
||||
func NewJobGet() *JobGet {
|
||||
return &JobGet{}
|
||||
}
|
||||
|
||||
func (j *JobGet) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(j)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
j.JobID = chi.URLParam(r, "jobID")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewJobGet()
|
||||
|
||||
// Job logs request parameters
|
||||
type JobLogs struct {
|
||||
JobID string
|
||||
Page int
|
||||
PerPage int
|
||||
}
|
||||
|
||||
func NewJobLogs() *JobLogs {
|
||||
return &JobLogs{}
|
||||
}
|
||||
|
||||
func (j *JobLogs) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(j)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
j.JobID = chi.URLParam(r, "jobID")
|
||||
j.Page = parseInt(chi.URLParam(r, "page"))
|
||||
j.PerPage = parseInt(chi.URLParam(r, "perPage"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewJobLogs()
|
||||
|
||||
// Job update request parameters
|
||||
type JobUpdate struct {
|
||||
JobID string
|
||||
Status string
|
||||
Log sqlxTypes.JSONText
|
||||
WorkflowID string
|
||||
StartAt string
|
||||
Parameters types.JobParameterSet
|
||||
}
|
||||
|
||||
func NewJobUpdate() *JobUpdate {
|
||||
return &JobUpdate{}
|
||||
}
|
||||
|
||||
func (j *JobUpdate) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(j)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
j.JobID = chi.URLParam(r, "jobID")
|
||||
if val, ok := post["status"]; ok {
|
||||
|
||||
j.Status = val
|
||||
}
|
||||
if val, ok := post["log"]; ok {
|
||||
|
||||
if j.Log, err = parseJSONTextWithErr(val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if val, ok := post["workflowID"]; ok {
|
||||
|
||||
j.WorkflowID = val
|
||||
}
|
||||
if val, ok := post["startAt"]; ok {
|
||||
|
||||
j.StartAt = val
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewJobUpdate()
|
||||
|
||||
// Job delete request parameters
|
||||
type JobDelete struct {
|
||||
JobID string
|
||||
}
|
||||
|
||||
func NewJobDelete() *JobDelete {
|
||||
return &JobDelete{}
|
||||
}
|
||||
|
||||
func (j *JobDelete) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(j)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
j.JobID = chi.URLParam(r, "jobID")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewJobDelete()
|
||||
@ -15,6 +15,7 @@ func MountRoutes(jwtAuth auth.TokenEncoder) func(chi.Router) {
|
||||
contentSvc = service.Content()
|
||||
pageSvc = service.Page()
|
||||
workflowSvc = service.Workflow()
|
||||
jobSvc = service.Job()
|
||||
)
|
||||
|
||||
var (
|
||||
@ -22,6 +23,7 @@ func MountRoutes(jwtAuth auth.TokenEncoder) func(chi.Router) {
|
||||
module = Module{}.New(moduleSvc, contentSvc)
|
||||
page = Page{}.New(pageSvc)
|
||||
workflow = Workflow{}.New(workflowSvc)
|
||||
job = Job{}.New(jobSvc)
|
||||
)
|
||||
|
||||
// Initialize handers & controllers.
|
||||
@ -34,6 +36,7 @@ func MountRoutes(jwtAuth auth.TokenEncoder) func(chi.Router) {
|
||||
handlers.NewPage(page).MountRoutes(r)
|
||||
handlers.NewModule(module).MountRoutes(r)
|
||||
handlers.NewWorkflow(workflow).MountRoutes(r)
|
||||
handlers.NewJob(job).MountRoutes(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,9 +2,11 @@ package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/crusttech/crust/crm/rest/request"
|
||||
"github.com/crusttech/crust/crm/service"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var _ = errors.Wrap
|
||||
|
||||
36
crm/service/job.go
Normal file
36
crm/service/job.go
Normal file
@ -0,0 +1,36 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
"github.com/crusttech/crust/crm/repository"
|
||||
_ "github.com/crusttech/crust/crm/types"
|
||||
)
|
||||
|
||||
type (
|
||||
job struct {
|
||||
db *factory.DB
|
||||
ctx context.Context
|
||||
|
||||
repository repository.JobRepository
|
||||
}
|
||||
|
||||
JobService interface {
|
||||
With(ctx context.Context) JobService
|
||||
}
|
||||
)
|
||||
|
||||
func Job() JobService {
|
||||
return (&job{}).With(context.Background())
|
||||
}
|
||||
|
||||
func (s *job) With(ctx context.Context) JobService {
|
||||
db := repository.DB(ctx)
|
||||
return &job{
|
||||
db: db,
|
||||
ctx: ctx,
|
||||
repository: repository.Job(ctx, db),
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@ var (
|
||||
DefaultModule ModuleService
|
||||
DefaultPage PageService
|
||||
DefaultWorkflow WorkflowService
|
||||
DefaultJob JobService
|
||||
)
|
||||
|
||||
func Init() {
|
||||
@ -20,5 +21,6 @@ func Init() {
|
||||
DefaultModule = Module()
|
||||
DefaultPage = Page()
|
||||
DefaultWorkflow = Workflow()
|
||||
DefaultJob = Job()
|
||||
})
|
||||
}
|
||||
|
||||
5
crm/types/job.go
Normal file
5
crm/types/job.go
Normal file
@ -0,0 +1,5 @@
|
||||
package types
|
||||
|
||||
type (
|
||||
JobParameterSet map[string]string
|
||||
)
|
||||
@ -32,6 +32,108 @@ CRM input field definitions
|
||||
|
||||
|
||||
|
||||
# Jobs
|
||||
|
||||
Workflow Jobs
|
||||
|
||||
## List jobs
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/job/` | HTTP/S | GET | |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| status | string | GET | Job status (`ok`, `error`, `running`, `cancelled` or `queued`) | N/A | NO |
|
||||
| page | int | GET | Page number (0 based) | N/A | NO |
|
||||
| perPage | int | GET | Returned items per page (default 50) | N/A | NO |
|
||||
|
||||
## Create a new job
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/job/` | HTTP/S | POST | |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| workflowID | string | POST | Workflow ID | N/A | YES |
|
||||
| startAt | string | POST | Start datetime for a delayed job | N/A | NO |
|
||||
| parameters | types.JobParameterSet | POST | Extra job parameters (map[string]string) | N/A | NO |
|
||||
|
||||
## Get job details
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/job/{jobID}` | HTTP/S | GET | |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| jobID | string | PATH | Job ID | N/A | YES |
|
||||
|
||||
## Get job logs
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/job/{jobID}/logs` | HTTP/S | GET | |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| jobID | string | PATH | Job ID | N/A | YES |
|
||||
| page | int | PATH | Page number (0 based) | N/A | NO |
|
||||
| perPage | int | PATH | Returned items per page (default 50) | N/A | NO |
|
||||
|
||||
## Update job details
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/job/{jobID}` | HTTP/S | POST | |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| jobID | string | PATH | Job ID | N/A | YES |
|
||||
| status | string | POST | Job status (`ok`, `error`, `running`, `cancelled` or `queued`) | N/A | NO |
|
||||
| log | sqlxTypes.JSONText | POST | Job log item (append-only) | N/A | NO |
|
||||
| workflowID | string | POST | Workflow ID | N/A | NO |
|
||||
| startAt | string | POST | Start datetime for a delayed job | N/A | NO |
|
||||
| parameters | types.JobParameterSet | POST | Extra job parameters (map[string]string) | N/A | NO |
|
||||
|
||||
## Cancel job
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/job/{jobID}` | HTTP/S | DELETE | |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| jobID | string | PATH | Job ID | N/A | YES |
|
||||
|
||||
|
||||
|
||||
|
||||
# Modules
|
||||
|
||||
CRM module definitions
|
||||
@ -550,7 +652,7 @@ CRM workflow definitions
|
||||
| onError | types.WorkflowTaskSet | POST | Type ID | N/A | NO |
|
||||
| timeout | int | POST | Timeout in seconds | N/A | NO |
|
||||
|
||||
## Get existing workflow details
|
||||
## Get workflow details
|
||||
|
||||
#### Method
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user