view pkg/controllers/scheduler.go @ 1590:2fdd8e57542d

Added DELETE /imports/scheduler/{id:[0-9]+} to delete a schedule from the scheduler.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 14 Dec 2018 12:34:12 +0100
parents e0bd82f6ee14
children 2d53065c95af
line wrap: on
line source

// This is Free Software under GNU Affero General Public License v >= 3.0
// without warranty, see README.md and license for details.
//
// SPDX-License-Identifier: AGPL-3.0-or-later
// License-Filename: LICENSES/AGPL-3.0.txt
//
// Copyright (C) 2018 by via donau
//   – Österreichische Wasserstraßen-Gesellschaft mbH
// Software engineering by Intevation GmbH
//
// Author(s):
//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>

package controllers

import (
	"database/sql"
	"errors"
	"fmt"
	"net/http"
	"strconv"

	"gemma.intevation.de/gemma/pkg/auth"
	"gemma.intevation.de/gemma/pkg/models"
	"gemma.intevation.de/gemma/pkg/scheduler"
	"github.com/gorilla/mux"
)

const (
	selectImportConfigurationSQL = `
SELECT
  id,
  username,
  kind,
  send_email,
  auto_accept,
  cron,
  url
FROM waterway.import_configuration
ORDER by id`

	insertImportConfigurationSQL = `
INSERT INTO waterway.import_configuration
(username, kind, cron, send_email, auto_accept, url)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id`

	hasImportConfigurationSQL = `
SELECT true FROM waterway.import_configuration
WHERE id = $1`

	deleteImportConfiguationSQL = `
DELETE FROM waterway.import_configuration
WHERE id = $1`
)

func deleteSchedule(
	_ interface{},
	req *http.Request,
	conn *sql.Conn,
) (jr JSONResult, err error) {

	ctx := req.Context()

	id, _ := strconv.ParseInt(mux.Vars(req)["id"], 10, 64)

	var tx *sql.Tx
	if tx, err = conn.BeginTx(ctx, nil); err != nil {
		return
	}
	defer tx.Rollback()

	var found bool
	err = tx.QueryRowContext(ctx, hasImportConfigurationSQL, id).Scan(&found)
	switch {
	case err == sql.ErrNoRows:
		err = JSONError{
			Code:    http.StatusNotFound,
			Message: fmt.Sprintf("No schedule %d found", id),
		}
		return
	case err != nil:
		return
	case !found:
		err = errors.New("Unexpected result")
		return
	}

	if _, err = tx.ExecContext(ctx, deleteImportConfiguationSQL, id); err != nil {
		return
	}

	// Remove from running scheduler.
	scheduler.UnbindByID(id)

	if err = tx.Commit(); err != nil {
		return
	}

	var result = struct {
		ID int64 `json:"id"`
	}{
		ID: id,
	}

	jr = JSONResult{Result: &result}
	return
}

func addSchedule(
	input interface{},
	req *http.Request,
	conn *sql.Conn,
) (jr JSONResult, err error) {

	importConfig := input.(*models.ImportConfig)

	session, _ := auth.GetSession(req)

	var cron, url sql.NullString

	if importConfig.Cron != nil {
		cron = sql.NullString{String: string(*importConfig.Cron), Valid: true}
	}
	if importConfig.URL != nil {
		url = sql.NullString{String: *importConfig.URL, Valid: true}
	}

	ctx := req.Context()

	var tx *sql.Tx

	if tx, err = conn.BeginTx(ctx, nil); err != nil {
		return
	}
	defer tx.Rollback()

	var id int64
	if err = tx.QueryRowContext(
		ctx,
		insertImportConfigurationSQL,
		session.User,
		string(importConfig.Kind),
		cron,
		importConfig.SendEMail,
		importConfig.AutoAccept,
		url,
	).Scan(&id); err != nil {
		return
	}

	// Need to start a scheduler job right away?
	if importConfig.Cron != nil {
		if err = scheduler.BindAction(
			string(importConfig.Kind),
			string(*importConfig.Cron),
			session.User,
			&id,
		); err != nil {
			return
		}
	}

	if err = tx.Commit(); err != nil {
		scheduler.UnbindByID(id)
	}

	var result = struct {
		ID int64 `json:"id"`
	}{
		ID: id,
	}

	jr = JSONResult{
		Code:   http.StatusCreated,
		Result: &result,
	}
	return
}

func listScheduler(
	_ interface{},
	req *http.Request,
	conn *sql.Conn,
) (jr JSONResult, err error) {

	ctx := req.Context()
	var rows *sql.Rows

	if rows, err = conn.QueryContext(ctx, selectImportConfigurationSQL); err != nil {
		return
	}
	defer rows.Close()

	list := []*models.IDImportConfig{}

	for rows.Next() {
		var (
			entry models.IDImportConfig
			kind  string
			cron  sql.NullString
			url   sql.NullString
		)
		if err = rows.Scan(
			&entry.ID,
			&kind,
			&entry.SendEMail,
			&entry.AutoAccept,
			&cron,
		); err != nil {
			return
		}
		entry.Kind = models.ImportKind(kind)
		if cron.Valid {
			cs := models.CronSpec(cron.String)
			entry.Cron = &cs
		}
		if url.Valid {
			entry.URL = &url.String
		}
		list = append(list, &entry)
	}

	if err = rows.Err(); err != nil {
		return
	}

	jr = JSONResult{Result: list}
	return
}