view pkg/imports/statsupdate.go @ 5415:4ad68ab239b7 marking-single-beam

Factored creation of default class breaks in SR import to be reused with markings, too.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 07 Jul 2021 12:01:28 +0200
parents 8e30b926b94d
children ade07a3f2cfd
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) 2021 by via donau
//   – Österreichische Wasserstraßen-Gesellschaft mbH
// Software engineering by Intevation GmbH
//
// Author(s):
//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>

package imports

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"time"

	"gemma.intevation.de/gemma/pkg/auth"
	"gemma.intevation.de/gemma/pkg/common"
	"gemma.intevation.de/gemma/pkg/models"
)

type StatsUpdate struct {
	models.QueueConfigurationType
	Name string `json:"name"`
}

const StatsUpdateJobKind JobKind = "statsupdate"

type statsUpdateJobCreator struct{}

func init() { RegisterJobCreator(StatsUpdateJobKind, statsUpdateJobCreator{}) }

func (statsUpdateJobCreator) Description() string { return "statsupdate" }

func (statsUpdateJobCreator) AutoAccept() bool { return true }

func (statsUpdateJobCreator) Create() Job { return new(StatsUpdate) }

func (statsUpdateJobCreator) Depends() [2][]string { return [2][]string{{}, {}} }

func (statsUpdateJobCreator) StageDone(context.Context, *sql.Tx, int64, Feedback) error {
	return nil
}

// RequiresRoles enforces to be a sys_admin to run this .
func (*StatsUpdate) RequiresRoles() auth.Roles { return auth.Roles{"sys_admin"} }

func (su *StatsUpdate) Description() (string, error) { return su.Name, nil }

func (*StatsUpdate) CleanUp() error { return nil }

func (su *StatsUpdate) MarshalAttributes(attrs common.Attributes) error {
	if err := su.QueueConfigurationType.MarshalAttributes(attrs); err != nil {
		return err
	}
	attrs.Set("name", su.Name)
	return nil
}

func (su *StatsUpdate) UnmarshalAttributes(attrs common.Attributes) error {
	if err := su.QueueConfigurationType.UnmarshalAttributes(attrs); err != nil {
		return err
	}
	name, found := attrs.Get("name")
	if !found {
		return errors.New("missing 'name' attribute")
	}
	su.Name = name
	return nil
}

const loadUpdateStatsScriptSQL = `SELECT script FROM sys_admin.stats_updates WHERE name = $1`

func (su *StatsUpdate) Do(
	ctx context.Context,
	importID int64,
	conn *sql.Conn,
	feedback Feedback,
) (interface{}, error) {

	start := time.Now()

	feedback.Info("Running stats update %s.", su.Name)

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

	var script string
	switch err := tx.QueryRowContext(ctx, loadUpdateStatsScriptSQL, su.Name).Scan(&script); {
	case err == sql.ErrNoRows:
		return nil, fmt.Errorf("no update script found for '%s'", su.Name)
	case err != nil:
		return nil, err
	}

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

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

	feedback.Info("Running stats update took %v.", time.Since(start))

	return nil, nil
}