<commit_before>package jobs

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/cozy/cozy-stack/pkg/consts"
	"github.com/cozy/cozy-stack/pkg/jobs"
	_ "github.com/cozy/cozy-stack/pkg/jobs/workers" // import all workers
	"github.com/cozy/cozy-stack/web/jsonapi"
	"github.com/cozy/cozy-stack/web/middlewares"
	"github.com/labstack/echo"
)

const typeTextEventStream = "text/event-stream"

type (
	apiJob struct {
		j *jobs.JobInfos
	}
	apiJobRequest struct {
		Arguments json.RawMessage  `json:"arguments"`
		Options   *jobs.JobOptions `json:"options"`
	}
	apiQueue struct {
		Count      int `json:"count"`
		workerType string
	}
	apiTrigger struct {
		t jobs.Trigger
	}
	apiTriggerRequest struct {
		Type            string           `json:"type"`
		Arguments       string           `json:"arguments"`
		WorkerType      string           `json:"worker"`
		WorkerArguments json.RawMessage  `json:"worker_arguments"`
		Options         *jobs.JobOptions `json:"options"`
	}
)

func (j *apiJob) ID() string                             { return j.j.ID }
func (j *apiJob) Rev() string                            { return "" }
func (j *apiJob) DocType() string                        { return consts.Jobs }
func (j *apiJob) SetID(_ string)                         {}
func (j *apiJob) SetRev(_ string)                        {}
func (j *apiJob) Relationships() jsonapi.RelationshipMap { return nil }
func (j *apiJob) Included() []jsonapi.Object             { return nil }
func (j *apiJob) SelfLink() string {
	return "/jobs/" + j.j.WorkerType + "/" + j.j.ID
}
func (j *apiJob) MarshalJSON() ([]byte, error) {
	return json.Marshal(j.j)
}

func (q *apiQueue) ID() string                             { return q.workerType }
func (q *apiQueue) Rev() string                            { return "" }
func (q *apiQueue) DocType() string                        { return consts.Queues }
func (q *apiQueue) SetID(_ string)                         {}
func (q *apiQueue) SetRev(_ string)                        {}
func (q *apiQueue) Relationships() jsonapi.RelationshipMap { return nil }
func (q *apiQueue) Included() []jsonapi.Object             { return nil }
func (q *apiQueue) SelfLink() string {
	return "/jobs/queue/" + q.workerType
}

func (t *apiTrigger) ID() string                             { return t.t.Infos().ID }
func (t *apiTrigger) Rev() string                            { return "" }
func (t *apiTrigger) DocType() string                        { return consts.Triggers }
func (t *apiTrigger) SetID(_ string)                         {}
func (t *apiTrigger) SetRev(_ string)                        {}
func (t *apiTrigger) Relationships() jsonapi.RelationshipMap { return nil }
func (t *apiTrigger) Included() []jsonapi.Object             { return nil }
func (t *apiTrigger) SelfLink() string {
	return "/jobs/triggers/" + t.ID()
}
func (t *apiTrigger) MarshalJSON() ([]byte, error) {
	return json.Marshal(t.t.Infos())
}

func getQueue(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	workerType := c.Param("worker-type")
	count, err := instance.JobsBroker().QueueLen(workerType)
	if err != nil {
		return err
	}
	o := &apiQueue{
		workerType: workerType,
		Count:      count,
	}
	return jsonapi.Data(c, http.StatusOK, o, nil)
}

func pushJob(c echo.Context) error {
	instance := middlewares.GetInstance(c)

	req := &apiJobRequest{}
	if err := c.Bind(&req); err != nil {
		return err
	}

	job, ch, err := instance.JobsBroker().PushJob(&jobs.JobRequest{
		WorkerType: c.Param("worker-type"),
		Options:    req.Options,
		Message: &jobs.Message{
			Type: jobs.JSONEncoding,
			Data: req.Arguments,
		},
	})
	if err != nil {
		return wrapJobsError(err)
	}

	accept := c.Request().Header.Get("Accept")
	if accept != typeTextEventStream {
		return jsonapi.Data(c, http.StatusAccepted, &apiJob{job}, nil)
	}

	w := c.Response().Writer
	w.Header().Set("Content-Type", typeTextEventStream)
	w.WriteHeader(200)
	if err := streamJob(job, w); err != nil {
		return nil
	}
	for job = range ch {
		if err := streamJob(job, w); err != nil {
			return nil
		}
	}
	return nil
}

func newTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	scheduler := instance.JobsScheduler()
	req := &apiTriggerRequest{}
	if err := c.Bind(&req); err != nil {
		return err
	}

	t, err := jobs.NewTrigger(&jobs.TriggerInfos{
		Type:       req.Type,
		WorkerType: req.WorkerType,
		Arguments:  req.Arguments,
		Options:    req.Options,
		Message: &jobs.Message{
			Type: jobs.JSONEncoding,
			Data: req.WorkerArguments,
		},
	})
	if err != nil {
		return err
	}
	if err = scheduler.Add(t); err != nil {
		return err
	}
	return jsonapi.Data(c, http.StatusCreated, &apiTrigger{t}, nil)
}

func getTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	scheduler := instance.JobsScheduler()
	t, err := scheduler.Get(c.Param("trigger-id"))
	if err != nil {
		return err
	}
	return jsonapi.Data(c, http.StatusOK, &apiTrigger{t}, nil)
}

func deleteTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	scheduler := instance.JobsScheduler()
	if err := scheduler.Delete(c.Param("trigger-id")); err != nil {
		return err
	}
	return nil
}
<commit_msg>Fix gometalinter<commit_after>package jobs

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/cozy/cozy-stack/pkg/consts"
	"github.com/cozy/cozy-stack/pkg/jobs"
	_ "github.com/cozy/cozy-stack/pkg/jobs/workers" // import all workers
	"github.com/cozy/cozy-stack/web/jsonapi"
	"github.com/cozy/cozy-stack/web/middlewares"
	"github.com/labstack/echo"
)

const typeTextEventStream = "text/event-stream"

type (
	apiJob struct {
		j *jobs.JobInfos
	}
	apiJobRequest struct {
		Arguments json.RawMessage  `json:"arguments"`
		Options   *jobs.JobOptions `json:"options"`
	}
	apiQueue struct {
		Count      int `json:"count"`
		workerType string
	}
	apiTrigger struct {
		t jobs.Trigger
	}
	apiTriggerRequest struct {
		Type            string           `json:"type"`
		Arguments       string           `json:"arguments"`
		WorkerType      string           `json:"worker"`
		WorkerArguments json.RawMessage  `json:"worker_arguments"`
		Options         *jobs.JobOptions `json:"options"`
	}
)

func (j *apiJob) ID() string                             { return j.j.ID }
func (j *apiJob) Rev() string                            { return "" }
func (j *apiJob) DocType() string                        { return consts.Jobs }
func (j *apiJob) SetID(_ string)                         {}
func (j *apiJob) SetRev(_ string)                        {}
func (j *apiJob) Relationships() jsonapi.RelationshipMap { return nil }
func (j *apiJob) Included() []jsonapi.Object             { return nil }
func (j *apiJob) SelfLink() string {
	return "/jobs/" + j.j.WorkerType + "/" + j.j.ID
}
func (j *apiJob) MarshalJSON() ([]byte, error) {
	return json.Marshal(j.j)
}

func (q *apiQueue) ID() string                             { return q.workerType }
func (q *apiQueue) Rev() string                            { return "" }
func (q *apiQueue) DocType() string                        { return consts.Queues }
func (q *apiQueue) SetID(_ string)                         {}
func (q *apiQueue) SetRev(_ string)                        {}
func (q *apiQueue) Relationships() jsonapi.RelationshipMap { return nil }
func (q *apiQueue) Included() []jsonapi.Object             { return nil }
func (q *apiQueue) SelfLink() string {
	return "/jobs/queue/" + q.workerType
}

func (t *apiTrigger) ID() string                             { return t.t.Infos().ID }
func (t *apiTrigger) Rev() string                            { return "" }
func (t *apiTrigger) DocType() string                        { return consts.Triggers }
func (t *apiTrigger) SetID(_ string)                         {}
func (t *apiTrigger) SetRev(_ string)                        {}
func (t *apiTrigger) Relationships() jsonapi.RelationshipMap { return nil }
func (t *apiTrigger) Included() []jsonapi.Object             { return nil }
func (t *apiTrigger) SelfLink() string {
	return "/jobs/triggers/" + t.ID()
}
func (t *apiTrigger) MarshalJSON() ([]byte, error) {
	return json.Marshal(t.t.Infos())
}

func getQueue(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	workerType := c.Param("worker-type")
	count, err := instance.JobsBroker().QueueLen(workerType)
	if err != nil {
		return err
	}
	o := &apiQueue{
		workerType: workerType,
		Count:      count,
	}
	return jsonapi.Data(c, http.StatusOK, o, nil)
}

func pushJob(c echo.Context) error {
	instance := middlewares.GetInstance(c)

	req := &apiJobRequest{}
	if err := c.Bind(&req); err != nil {
		return err
	}

	job, ch, err := instance.JobsBroker().PushJob(&jobs.JobRequest{
		WorkerType: c.Param("worker-type"),
		Options:    req.Options,
		Message: &jobs.Message{
			Type: jobs.JSONEncoding,
			Data: req.Arguments,
		},
	})
	if err != nil {
		return wrapJobsError(err)
	}

	accept := c.Request().Header.Get("Accept")
	if accept != typeTextEventStream {
		return jsonapi.Data(c, http.StatusAccepted, &apiJob{job}, nil)
	}

	w := c.Response().Writer
	w.Header().Set("Content-Type", typeTextEventStream)
	w.WriteHeader(200)
	if err := streamJob(job, w); err != nil {
		return nil
	}
	for job = range ch {
		if err := streamJob(job, w); err != nil {
			return nil
		}
	}
	return nil
}

func newTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	scheduler := instance.JobsScheduler()
	req := &apiTriggerRequest{}
	if err := c.Bind(&req); err != nil {
		return err
	}

	t, err := jobs.NewTrigger(&jobs.TriggerInfos{
		Type:       req.Type,
		WorkerType: req.WorkerType,
		Arguments:  req.Arguments,
		Options:    req.Options,
		Message: &jobs.Message{
			Type: jobs.JSONEncoding,
			Data: req.WorkerArguments,
		},
	})
	if err != nil {
		return err
	}
	if err = scheduler.Add(t); err != nil {
		return err
	}
	return jsonapi.Data(c, http.StatusCreated, &apiTrigger{t}, nil)
}

func getTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	scheduler := instance.JobsScheduler()
	t, err := scheduler.Get(c.Param("trigger-id"))
	if err != nil {
		return err
	}
	return jsonapi.Data(c, http.StatusOK, &apiTrigger{t}, nil)
}

func deleteTrigger(c echo.Context) error {
	instance := middlewares.GetInstance(c)
	scheduler := instance.JobsScheduler()
	return scheduler.Delete(c.Param("trigger-id"))
}

{'fraction_non_alphanumeric': 0.14112746997287873, 'fraction_numerical': 0.000581170089112747, 'mean_word_length': 2.753180661577608, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7173772', 'n_tokens_mistral': 3559, 'n_tokens_neox': 3407, 'n_words': 832}