Ctrl K
ComunidadGuías…

tariff/wrapper.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package tariff

import (
	"context"
	"fmt"
	"sync"
	"time"

	"github.com/evcc-io/evcc/api"
	"github.com/evcc-io/evcc/util"
)

// retryInterval is the minimum time between attempts to create an unavailable tariff
const retryInterval = 15 * time.Minute

// Wrapper wraps an api.Tariff that could not be created and retries creating it
type Wrapper struct {
	mu     sync.Mutex
	log    *util.Logger
	ctx    context.Context
	typ    string
	config map[string]any

	tariff    api.Tariff
	err       error
	retriedAt time.Time // last creation attempt
}

var _ api.Tariff = (*Wrapper)(nil)

// NewWrapper creates a wrapper for a tariff that could not be created
func NewWrapper(ctx context.Context, typ string, other map[string]any, err error) api.Tariff {
	return &Wrapper{
		log:       util.NewLogger("tariff"),
		ctx:       ctx,
		typ:       typ,
		config:    other,
		err:       err,
		retriedAt: time.Now(), // creation has just failed
	}
}

// WrappedConfig indicates a device with wrapped configuration
func (v *Wrapper) WrappedConfig() (string, map[string]any) {
	return v.typ, v.config
}

// instance returns the tariff once created. Creation is retried at most once per retryInterval.
func (v *Wrapper) instance() api.Tariff {
	if v.tariff != nil || time.Since(v.retriedAt) < retryInterval {
		return v.tariff
	}

	v.retriedAt = time.Now()

	t, err := NewFromConfig(v.ctx, v.typ, v.config)
	if err != nil {
		v.err = err
		v.log.WARN.Printf("creating tariff failed: %v", err)
		return nil
	}

	v.tariff = t
	v.log.INFO.Printf("tariff available: %s", util.TypeWithTemplateName(v.typ, v.config))

	return t
}

// Rates implements the api.Tariff interface
func (v *Wrapper) Rates() (api.Rates, error) {
	v.mu.Lock()
	defer v.mu.Unlock()

	if t := v.instance(); t != nil {
		return t.Rates()
	}

	return nil, fmt.Errorf("tariff not available: %w", v.err)
}

// Type implements the api.Tariff interface
func (v *Wrapper) Type() api.TariffType {
	v.mu.Lock()
	defer v.mu.Unlock()

	if t := v.instance(); t != nil {
		return t.Type()
	}

	return 0
}