refactor: split go-pkg

This commit is contained in:
xuu 2023-07-12 17:35:02 -06:00
parent d67d768c1e
commit 0f665d3484
Signed by: xuu
GPG Key ID: C63E6D61F3035024
80 changed files with 785 additions and 3993 deletions

View File

@ -1,23 +1,23 @@
scalar Time scalar Time
scalar Map scalar Map
type Connection @goModel(model: "go.sour.is/ev/pkg/gql.Connection") { type Connection @goModel(model: "go.sour.is/pkg/gql.Connection") {
paging: PageInfo! paging: PageInfo!
edges: [Edge!]! edges: [Edge!]!
} }
input PageInput @goModel(model: "go.sour.is/ev/pkg/gql.PageInput") { input PageInput @goModel(model: "go.sour.is/pkg/gql.PageInput") {
after: Int = 0 after: Int = 0
before: Int before: Int
count: Int = 30 count: Int = 30
} }
type PageInfo @goModel(model: "go.sour.is/ev/pkg/gql.PageInfo") { type PageInfo @goModel(model: "go.sour.is/pkg/gql.PageInfo") {
next: Boolean! next: Boolean!
prev: Boolean! prev: Boolean!
begin: Int! begin: Int!
end: Int! end: Int!
} }
interface Edge @goModel(model: "go.sour.is/ev/pkg/gql.Edge"){ interface Edge @goModel(model: "go.sour.is/pkg/gql.Edge"){
id: ID! id: ID!
} }

View File

@ -4,12 +4,13 @@ import (
"context" "context"
"github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql"
"go.sour.is/pkg/gql"
"go.sour.is/pkg/gql/resolver"
"go.sour.is/ev/app/msgbus" "go.sour.is/ev/app/msgbus"
"go.sour.is/ev/app/salty" "go.sour.is/ev/app/salty"
"go.sour.is/ev/internal/graph/generated" "go.sour.is/ev/internal/graph/generated"
"go.sour.is/ev/pkg/es" "go.sour.is/ev/pkg/es"
"go.sour.is/ev/pkg/gql"
"go.sour.is/ev/pkg/gql/resolver"
) )
type Resolver struct { type Resolver struct {

View File

@ -14,24 +14,23 @@ import (
"time" "time"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"go.opentelemetry.io/otel/metric/instrument" "go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/instrument/syncint64"
"go.opentelemetry.io/otel/metric/unit"
"go.uber.org/multierr" "go.uber.org/multierr"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event"
"go.sour.is/ev/pkg/gql" "go.sour.is/pkg/gql"
"go.sour.is/pkg/lg"
) )
type service struct { type service struct {
es *ev.EventStore es *ev.EventStore
m_gql_posts syncint64.Counter m_gql_posts metric.Int64Counter
m_gql_post_added syncint64.Counter m_gql_post_added metric.Int64Counter
m_gql_post_added_event syncint64.Counter m_gql_post_added_event metric.Int64Counter
m_req_time syncint64.Histogram m_req_time metric.Int64Histogram
} }
type MsgbusResolver interface { type MsgbusResolver interface {
@ -56,24 +55,24 @@ func New(ctx context.Context, es *ev.EventStore) (*service, error) {
svc := &service{es: es} svc := &service{es: es}
var err, errs error var err, errs error
svc.m_gql_posts, err = m.SyncInt64().Counter("msgbus_posts", svc.m_gql_posts, err = m.Int64Counter("msgbus_posts",
instrument.WithDescription("msgbus graphql posts requests"), metric.WithDescription("msgbus graphql posts requests"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
svc.m_gql_post_added, err = m.SyncInt64().Counter("msgbus_post_added", svc.m_gql_post_added, err = m.Int64Counter("msgbus_post_added",
instrument.WithDescription("msgbus graphql post added subcription requests"), metric.WithDescription("msgbus graphql post added subcription requests"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
svc.m_gql_post_added_event, err = m.SyncInt64().Counter("msgbus_post_event", svc.m_gql_post_added_event, err = m.Int64Counter("msgbus_post_event",
instrument.WithDescription("msgbus graphql post added subscription events"), metric.WithDescription("msgbus graphql post added subscription events"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
svc.m_req_time, err = m.SyncInt64().Histogram("msgbus_request_time", svc.m_req_time, err = m.Int64Histogram("msgbus_request_time",
instrument.WithDescription("msgbus graphql post added subscription events"), metric.WithDescription("msgbus graphql post added subscription events"),
instrument.WithUnit(unit.Unit("ns")), metric.WithUnit("ns"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)

View File

@ -5,7 +5,7 @@ import (
"github.com/tj/go-semver" "github.com/tj/go-semver"
"go.sour.is/ev/pkg/es/event" "go.sour.is/ev/pkg/event"
) )
type Info struct { type Info struct {

View File

@ -7,8 +7,9 @@ import (
"time" "time"
"github.com/keys-pub/keys/json" "github.com/keys-pub/keys/json"
"go.sour.is/ev/pkg/es/event" "go.sour.is/pkg/set"
"go.sour.is/ev/pkg/set"
"go.sour.is/ev/pkg/event"
) )
type Time time.Time type Time time.Time

View File

@ -9,8 +9,8 @@ import (
"time" "time"
"github.com/oklog/ulid" "github.com/oklog/ulid"
"go.sour.is/ev/pkg/es/event" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/set" "go.sour.is/pkg/set"
) )
type Request struct { type Request struct {

View File

@ -19,10 +19,10 @@ import (
"github.com/oklog/ulid/v2" "github.com/oklog/ulid/v2"
contentnegotiation "gitlab.com/jamietanna/content-negotiation-go" contentnegotiation "gitlab.com/jamietanna/content-negotiation-go"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.sour.is/pkg/lg"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event"
) )
var ( var (
@ -656,7 +656,6 @@ func fnOrderByPeer(rq *Request) listPeer {
v := peers[i] v := peers[i]
sort.Sort(v.Results) sort.Sort(v.Results)
v.Name = v.Results[0].Name v.Name = v.Results[0].Name
v.Country = v.Results[0].Country v.Country = v.Results[0].Country
v.Latency = v.Results[0].Latency v.Latency = v.Results[0].Latency

View File

@ -10,9 +10,9 @@ import (
"time" "time"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/set" "go.sour.is/pkg/set"
) )
// RefreshJob retrieves peer info from the peerdb // RefreshJob retrieves peer info from the peerdb

View File

@ -6,11 +6,12 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"go.sour.is/ev" "go.sour.is/pkg/lg"
"go.sour.is/ev/internal/lg" "go.sour.is/pkg/locker"
"go.sour.is/ev/pkg/es/event"
"go.sour.is/ev/pkg/locker"
"go.uber.org/multierr" "go.uber.org/multierr"
"go.sour.is/ev"
"go.sour.is/ev/pkg/event"
) )
const ( const (

View File

@ -11,10 +11,9 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"go.opentelemetry.io/otel/metric/instrument" "go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/instrument/syncint64" "go.sour.is/pkg/authreq"
"go.sour.is/ev/internal/lg" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/authreq"
"go.uber.org/multierr" "go.uber.org/multierr"
) )
@ -30,9 +29,9 @@ func WithBlobStore(path string) *withBlobStore {
type withBlobStore struct { type withBlobStore struct {
path string path string
m_get_blob syncint64.Counter m_get_blob metric.Int64Counter
m_put_blob syncint64.Counter m_put_blob metric.Int64Counter
m_delete_blob syncint64.Counter m_delete_blob metric.Int64Counter
} }
func (o *withBlobStore) ApplySalty(s *service) {} func (o *withBlobStore) ApplySalty(s *service) {}
@ -49,18 +48,18 @@ func (o *withBlobStore) Setup(ctx context.Context) error {
} }
m := lg.Meter(ctx) m := lg.Meter(ctx)
o.m_get_blob, err = m.SyncInt64().Counter("salty_get_blob", o.m_get_blob, err = m.Int64Counter("salty_get_blob",
instrument.WithDescription("salty get blob called"), metric.WithDescription("salty get blob called"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
o.m_put_blob, err = m.SyncInt64().Counter("salty_put_blob", o.m_put_blob, err = m.Int64Counter("salty_put_blob",
instrument.WithDescription("salty put blob called"), metric.WithDescription("salty put blob called"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
o.m_delete_blob, err = m.SyncInt64().Counter("salty_delete_blob", o.m_delete_blob, err = m.Int64Counter("salty_delete_blob",
instrument.WithDescription("salty delete blob called"), metric.WithDescription("salty delete blob called"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)

View File

@ -11,7 +11,7 @@ import (
"github.com/keys-pub/keys" "github.com/keys-pub/keys"
"go.sour.is/ev/internal/lg" "go.sour.is/pkg/lg"
) )
// Config represents a Salty Config for a User which at a minimum is required // Config represents a Salty Config for a User which at a minimum is required

View File

@ -12,8 +12,8 @@ import (
"github.com/keys-pub/keys" "github.com/keys-pub/keys"
"github.com/oklog/ulid/v2" "github.com/oklog/ulid/v2"
"go.sour.is/ev/pkg/es/event" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/gql" "go.sour.is/pkg/gql"
) )
type SaltyUser struct { type SaltyUser struct {

View File

@ -14,15 +14,13 @@ import (
"github.com/keys-pub/keys" "github.com/keys-pub/keys"
"go.mills.io/saltyim" "go.mills.io/saltyim"
"go.opentelemetry.io/otel/metric/instrument" "go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/instrument/syncint64"
"go.opentelemetry.io/otel/metric/unit"
"go.uber.org/multierr" "go.uber.org/multierr"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event" "go.sour.is/pkg/gql"
"go.sour.is/ev/pkg/gql" "go.sour.is/pkg/lg"
) )
type DNSResolver interface { type DNSResolver interface {
@ -34,13 +32,13 @@ type service struct {
es *ev.EventStore es *ev.EventStore
dns DNSResolver dns DNSResolver
m_create_user syncint64.Counter m_create_user metric.Int64Counter
m_get_user syncint64.Counter m_get_user metric.Int64Counter
m_api_ping syncint64.Counter m_api_ping metric.Int64Counter
m_api_register syncint64.Counter m_api_register metric.Int64Counter
m_api_lookup syncint64.Counter m_api_lookup metric.Int64Counter
m_api_send syncint64.Counter m_api_send metric.Int64Counter
m_req_time syncint64.Histogram m_req_time metric.Int64Histogram
opts []Option opts []Option
} }
@ -93,39 +91,39 @@ func New(ctx context.Context, es *ev.EventStore, opts ...Option) (*service, erro
} }
var err, errs error var err, errs error
svc.m_create_user, err = m.SyncInt64().Counter("salty_create_user", svc.m_create_user, err = m.Int64Counter("salty_create_user",
instrument.WithDescription("salty create user graphql called"), metric.WithDescription("salty create user graphql called"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
svc.m_get_user, err = m.SyncInt64().Counter("salty_get_user", svc.m_get_user, err = m.Int64Counter("salty_get_user",
instrument.WithDescription("salty get user graphql called"), metric.WithDescription("salty get user graphql called"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
svc.m_api_ping, err = m.SyncInt64().Counter("salty_api_ping", svc.m_api_ping, err = m.Int64Counter("salty_api_ping",
instrument.WithDescription("salty api ping called"), metric.WithDescription("salty api ping called"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
svc.m_api_register, err = m.SyncInt64().Counter("salty_api_register", svc.m_api_register, err = m.Int64Counter("salty_api_register",
instrument.WithDescription("salty api register"), metric.WithDescription("salty api register"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
svc.m_api_lookup, err = m.SyncInt64().Counter("salty_api_lookup", svc.m_api_lookup, err = m.Int64Counter("salty_api_lookup",
instrument.WithDescription("salty api ping lookup"), metric.WithDescription("salty api ping lookup"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
svc.m_api_send, err = m.SyncInt64().Counter("salty_api_send", svc.m_api_send, err = m.Int64Counter("salty_api_send",
instrument.WithDescription("salty api ping send"), metric.WithDescription("salty api ping send"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
svc.m_req_time, err = m.SyncInt64().Histogram("salty_request_time", svc.m_req_time, err = m.Int64Histogram("salty_request_time",
instrument.WithDescription("histogram of requests"), metric.WithDescription("histogram of requests"),
instrument.WithUnit(unit.Unit("ns")), metric.WithUnit("ns"),
) )
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)

View File

@ -1,7 +1,7 @@
package webfinger package webfinger
import ( import (
"go.sour.is/ev/pkg/es/event" "go.sour.is/ev/pkg/event"
) )
type SubjectSet struct { type SubjectSet struct {

View File

@ -8,10 +8,11 @@ import (
"hash/fnv" "hash/fnv"
"sort" "sort"
"go.sour.is/ev/pkg/es/event" "go.sour.is/pkg/set"
"go.sour.is/ev/pkg/set" "go.sour.is/pkg/slice"
"go.sour.is/ev/pkg/slice"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"go.sour.is/ev/pkg/event"
) )
func StreamID(subject string) string { func StreamID(subject string) string {

View File

@ -12,14 +12,14 @@ import (
jwt "github.com/golang-jwt/jwt/v4" jwt "github.com/golang-jwt/jwt/v4"
"github.com/matryer/is" "github.com/matryer/is"
"go.sour.is/ev"
"go.uber.org/multierr" "go.uber.org/multierr"
"go.sour.is/ev"
"go.sour.is/ev/app/webfinger" "go.sour.is/ev/app/webfinger"
memstore "go.sour.is/ev/pkg/es/driver/mem-store" memstore "go.sour.is/ev/pkg/driver/mem-store"
"go.sour.is/ev/pkg/es/driver/projecter" "go.sour.is/ev/pkg/driver/projecter"
"go.sour.is/ev/pkg/es/driver/streamer" "go.sour.is/ev/pkg/driver/streamer"
"go.sour.is/ev/pkg/es/event" "go.sour.is/ev/pkg/event"
) )
func TestParseJRD(t *testing.T) { func TestParseJRD(t *testing.T) {

View File

@ -20,10 +20,11 @@ import (
"strings" "strings"
"github.com/golang-jwt/jwt/v4" "github.com/golang-jwt/jwt/v4"
"go.sour.is/pkg/lg"
"go.sour.is/pkg/set"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event"
"go.sour.is/ev/pkg/set"
) )
var ( var (

View File

@ -6,10 +6,10 @@ import (
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/app/msgbus" "go.sour.is/ev/app/msgbus"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/driver/projecter"
"go.sour.is/ev/pkg/service" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/es/driver/projecter" "go.sour.is/pkg/service"
"go.sour.is/ev/pkg/slice" "go.sour.is/pkg/slice"
) )
var _ = apps.Register(50, func(ctx context.Context, svc *service.Harness) error { var _ = apps.Register(50, func(ctx context.Context, svc *service.Harness) error {

View File

@ -4,13 +4,14 @@ import (
"context" "context"
"fmt" "fmt"
"go.sour.is/pkg/env"
"go.sour.is/pkg/lg"
"go.sour.is/pkg/service"
"go.sour.is/pkg/slice"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/app/peerfinder" "go.sour.is/ev/app/peerfinder"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/driver/projecter"
"go.sour.is/ev/pkg/env"
"go.sour.is/ev/pkg/es/driver/projecter"
"go.sour.is/ev/pkg/service"
"go.sour.is/ev/pkg/slice"
) )
var _ = apps.Register(50, func(ctx context.Context, svc *service.Harness) error { var _ = apps.Register(50, func(ctx context.Context, svc *service.Harness) error {

View File

@ -11,10 +11,10 @@ import (
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/app/salty" "go.sour.is/ev/app/salty"
"go.sour.is/ev/internal/lg" "go.sour.is/pkg/env"
"go.sour.is/ev/pkg/env" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/service" "go.sour.is/pkg/service"
"go.sour.is/ev/pkg/slice" "go.sour.is/pkg/slice"
) )
var _ = apps.Register(50, func(ctx context.Context, svc *service.Harness) error { var _ = apps.Register(50, func(ctx context.Context, svc *service.Harness) error {

View File

@ -3,8 +3,8 @@ package main
import ( import (
"context" "context"
"go.sour.is/ev/internal/lg" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/service" "go.sour.is/pkg/service"
) )
var _ = apps.Register(50, func(ctx context.Context, svc *service.Harness) error { var _ = apps.Register(50, func(ctx context.Context, svc *service.Harness) error {

View File

@ -7,12 +7,13 @@ import (
"time" "time"
"github.com/patrickmn/go-cache" "github.com/patrickmn/go-cache"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/app/webfinger" "go.sour.is/ev/app/webfinger"
"go.sour.is/ev/internal/lg" "go.sour.is/pkg/env"
"go.sour.is/ev/pkg/env" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/service" "go.sour.is/pkg/service"
"go.sour.is/ev/pkg/slice" "go.sour.is/pkg/slice"
) )
var ( var (

View File

@ -8,8 +8,8 @@ import (
"os" "os"
"os/signal" "os/signal"
"go.sour.is/ev/internal/lg" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/service" "go.sour.is/pkg/service"
) )
var apps service.Apps var apps service.Apps

View File

@ -3,18 +3,19 @@ package main
import ( import (
"context" "context"
"go.sour.is/ev" "go.sour.is/pkg/env"
"go.sour.is/ev/internal/lg" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/env" "go.sour.is/pkg/service"
"go.sour.is/ev/pkg/es"
diskstore "go.sour.is/ev/pkg/es/driver/disk-store"
memstore "go.sour.is/ev/pkg/es/driver/mem-store"
"go.sour.is/ev/pkg/es/driver/projecter"
resolvelinks "go.sour.is/ev/pkg/es/driver/resolve-links"
"go.sour.is/ev/pkg/es/driver/streamer"
"go.sour.is/ev/pkg/es/event"
"go.sour.is/ev/pkg/service"
"go.uber.org/multierr" "go.uber.org/multierr"
"go.sour.is/ev"
diskstore "go.sour.is/ev/pkg/driver/disk-store"
memstore "go.sour.is/ev/pkg/driver/mem-store"
"go.sour.is/ev/pkg/driver/projecter"
resolvelinks "go.sour.is/ev/pkg/driver/resolve-links"
"go.sour.is/ev/pkg/driver/streamer"
"go.sour.is/ev/pkg/es"
"go.sour.is/ev/pkg/event"
) )
var _ = apps.Register(10, func(ctx context.Context, svc *service.Harness) error { var _ = apps.Register(10, func(ctx context.Context, svc *service.Harness) error {

View File

@ -4,12 +4,13 @@ import (
"context" "context"
"net/http" "net/http"
"go.sour.is/pkg/gql/resolver"
"go.sour.is/pkg/lg"
"go.sour.is/pkg/mux"
"go.sour.is/pkg/service"
"go.sour.is/pkg/slice"
"go.sour.is/ev/app/gql" "go.sour.is/ev/app/gql"
"go.sour.is/ev/internal/lg"
"go.sour.is/ev/pkg/gql/resolver"
"go.sour.is/ev/pkg/mux"
"go.sour.is/ev/pkg/service"
"go.sour.is/ev/pkg/slice"
) )
var _ = apps.Register(90, func(ctx context.Context, svc *service.Harness) error { var _ = apps.Register(90, func(ctx context.Context, svc *service.Harness) error {

View File

@ -7,11 +7,12 @@ import (
"strings" "strings"
"github.com/rs/cors" "github.com/rs/cors"
"go.sour.is/ev/internal/lg"
"go.sour.is/ev/pkg/env" "go.sour.is/pkg/env"
"go.sour.is/ev/pkg/mux" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/service" "go.sour.is/pkg/mux"
"go.sour.is/ev/pkg/slice" "go.sour.is/pkg/service"
"go.sour.is/pkg/slice"
) )
var _ = apps.Register(20, func(ctx context.Context, svc *service.Harness) error { var _ = apps.Register(20, func(ctx context.Context, svc *service.Harness) error {

View File

@ -16,10 +16,10 @@ import (
"strings" "strings"
"github.com/docopt/docopt-go" "github.com/docopt/docopt-go"
"go.sour.is/pkg/xdg"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"go.sour.is/ev/app/webfinger" "go.sour.is/ev/app/webfinger"
"go.sour.is/ev/cmd/webfinger-cli/xdg"
) )
var usage = `Webfinger CLI. var usage = `Webfinger CLI.

View File

@ -1,30 +0,0 @@
//go:build darwin
// +build darwin
package xdg
func literal(name string) string {
return "$" + name
}
const (
defaultDataHome = "~/Library/Application Support"
defaultDataDirs = "/Library/Application Support"
defaultConfigHome = "~/Library/Preferences"
defaultConfigDirs = "/Library/Preferences"
defaultCacheHome = "~/Library/Caches"
defaultStateHome = "~/Library/Caches"
defaultRuntime = "~/Library/Application Support"
defaultDesktop = "~/Desktop"
defaultDownload = "~/Downloads"
defaultDocuments = "~/Documents"
defaultMusic = "~/Music"
defaultPictures = "~/Pictures"
defaultVideos = "~/Videos"
defaultTemplates = "~/Templates"
defaultPublic = "~/Public"
defaultApplicationDirs = "~/Applications:/Applications"
defaultFontDirs = "~/Library/Fonts:/Library/Fonts:/System/Library/Fonts:/Network/Library/Fonts"
)

View File

@ -1,30 +0,0 @@
//go:build linux
// +build linux
package xdg
func literal(name string) string {
return "$" + name
}
const (
defaultDataHome = "~/.local/share"
defaultDataDirs = "/usr/local/share:/usr/share"
defaultConfigHome = "~/.config"
defaultConfigDirs = "/etc/xdg"
defaultCacheHome = "~/.local/cache"
defaultStateHome = "~/.local/state"
defaultRuntime = "/run/user/$UID"
defaultDesktop = "~/Desktop"
defaultDownload = "~/Downloads"
defaultDocuments = "~/Documents"
defaultMusic = "~/Music"
defaultPictures = "~/Pictures"
defaultVideos = "~/Videos"
defaultTemplates = "~/Templates"
defaultPublic = "~/Public"
defaultApplicationDirs = "~/Applications:/Applications"
defaultFontDirs = "~/.local/share/fonts:/usr/local/share/fonts:/usr/share/fonts:~/.fonts"
)

View File

@ -1,30 +0,0 @@
//go:build windows
// +build windows
package xdg
func literal(name string) string {
return "%" + name + "%"
}
const (
defaultDataHome = `%LOCALAPPDATA%`
defaultDataDirs = `%APPDATA%\Roaming;%ProgramData%`
defaultConfigHome = `%LOCALAPPDATA%`
defaultConfigDirs = `%ProgramData%`
defaultCacheHome = `%LOCALAPPDATA%\cache`
defaultStateHome = `%LOCALAPPDATA%\state`
defaultRuntime = `%LOCALAPPDATA%`
defaultDesktop = `%USERPROFILE%\Desktop`
defaultDownload = `%USERPROFILE%\Downloads`
defaultDocuments = `%USERPROFILE%\Documents`
defaultMusic = `%USERPROFILE%\Music`
defaultPictures = `%USERPROFILE%\Pictures`
defaultVideos = `%USERPROFILE%\Videos`
defaultTemplates = `%USERPROFILE%\Templates`
defaultPublic = `%USERPROFILE%\Public`
defaultApplicationDirs = `%APPDATA%\Roaming\Microsoft\Windows\Start Menu\Programs`
defaultFontDirs = `%windir%\Fonts;%LOCALAPPDATA%\Microsoft\Windows\Fonts`
)

View File

@ -1,52 +0,0 @@
package xdg
import (
"os"
"path/filepath"
"strings"
)
var (
EnvDataHome = setENV("XDG_DATA_HOME", defaultDataHome)
EnvDataDirs = setENV("XDG_DATA_DIRS", defaultDataDirs)
EnvConfigHome = setENV("XDG_CONFIG_HOME", defaultConfigHome)
EnvConfigDirs = setENV("XDG_CONFIG_DIRS", defaultConfigDirs)
EnvCacheHome = setENV("XDG_CACHE_HOME", defaultCacheHome)
EnvStateHome = setENV("XDG_STATE_HOME", defaultStateHome)
EnvRuntime = setENV("XDG_RUNTIME_DIR", defaultRuntime)
EnvDesktopDir = setENV("XDG_DESKTOP_DIR", defaultDesktop)
EnvDownloadDir = setENV("XDG_DOWNLOAD_DIR", defaultDownload)
EnvDocumentsDir = setENV("XDG_DOCUMENTS_DIR", defaultDocuments)
EnvMusicDir = setENV("XDG_MUSIC_DIR", defaultMusic)
EnvPicturesDir = setENV("XDG_PICTURES_DIR", defaultPictures)
EnvVideosDir = setENV("XDG_VIDEOS_DIR", defaultVideos)
EnvTemplatesDir = setENV("XDG_TEMPLATES_DIR", defaultTemplates)
EnvPublicShareDir = setENV("XDG_PUBLICSHARE_DIR", defaultPublic)
EnvApplicationsDir = setENV("XDG_APPLICATIONS_DIR", defaultApplicationDirs)
EnvFontsDir = setENV("XDG_FONTS_DIR", defaultFontDirs)
)
func setENV(name, value string) string {
if _, ok := os.LookupEnv(name); !ok {
os.Setenv(name, value)
}
return literal(name)
}
func Get(base, suffix string) string {
paths := strings.Split(os.ExpandEnv(base), string(os.PathListSeparator))
for i, path := range paths {
if strings.HasPrefix(path, "~") {
path = strings.Replace(path, "~", getHome(), 1)
}
paths[i] = os.ExpandEnv(filepath.Join(path, suffix))
}
return strings.Join(paths, string(os.PathListSeparator))
}
func getHome() string {
home, err := os.UserHomeDir()
if err != nil {
return "."
}
return home
}

30
ev.go
View File

@ -8,13 +8,13 @@ import (
"strings" "strings"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric/instrument/syncint64" "go.opentelemetry.io/otel/metric"
"go.uber.org/multierr" "go.uber.org/multierr"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/driver"
"go.sour.is/ev/pkg/es/driver" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/locker" "go.sour.is/pkg/locker"
) )
type config struct { type config struct {
@ -32,19 +32,19 @@ func Init(ctx context.Context) error {
m := lg.Meter(ctx) m := lg.Meter(ctx)
var err, errs error var err, errs error
Mes_open, err = m.SyncInt64().Counter("es_open") Mes_open, err = m.Int64Counter("es_open")
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
Mes_read, err = m.SyncInt64().Counter("es_read") Mes_read, err = m.Int64Counter("es_read")
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
Mes_load, err = m.SyncInt64().Counter("es_load") Mes_load, err = m.Int64Counter("es_load")
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
Mes_save, err = m.SyncInt64().Counter("es_save") Mes_save, err = m.Int64Counter("es_save")
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
Mes_append, err = m.SyncInt64().Counter("es_append") Mes_append, err = m.Int64Counter("es_append")
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
return errs return errs
@ -68,11 +68,11 @@ type EventStore struct {
} }
var ( var (
Mes_open syncint64.Counter Mes_open metric.Int64Counter
Mes_read syncint64.Counter Mes_read metric.Int64Counter
Mes_load syncint64.Counter Mes_load metric.Int64Counter
Mes_save syncint64.Counter Mes_save metric.Int64Counter
Mes_append syncint64.Counter Mes_append metric.Int64Counter
) )
func Open(ctx context.Context, dsn string, options ...Option) (*EventStore, error) { func Open(ctx context.Context, dsn string, options ...Option) (*EventStore, error) {

View File

@ -12,11 +12,11 @@ import (
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/app/peerfinder" "go.sour.is/ev/app/peerfinder"
memstore "go.sour.is/ev/pkg/es/driver/mem-store" memstore "go.sour.is/ev/pkg/driver/mem-store"
"go.sour.is/ev/pkg/es/driver/projecter" "go.sour.is/ev/pkg/driver/projecter"
resolvelinks "go.sour.is/ev/pkg/es/driver/resolve-links" resolvelinks "go.sour.is/ev/pkg/driver/resolve-links"
"go.sour.is/ev/pkg/es/driver/streamer" "go.sour.is/ev/pkg/driver/streamer"
"go.sour.is/ev/pkg/es/event" "go.sour.is/ev/pkg/event"
) )
var ( var (

86
go.mod
View File

@ -3,30 +3,33 @@ module go.sour.is/ev
go 1.19 go 1.19
require ( require (
github.com/99designs/gqlgen v0.17.13 github.com/99designs/gqlgen v0.17.34
github.com/go-logr/stdr v1.2.2 github.com/go-logr/stdr v1.2.2 // indirect
github.com/gorilla/websocket v1.5.0 github.com/gorilla/websocket v1.5.0
github.com/logzio/logzio-go v1.0.6 github.com/ravilushqa/otelgqlgen v0.13.1 // indirect
github.com/ravilushqa/otelgqlgen v0.9.0
github.com/rs/cors v1.8.2 github.com/rs/cors v1.8.2
github.com/tidwall/wal v1.1.7 github.com/tidwall/wal v1.1.7
github.com/vektah/gqlparser/v2 v2.4.7 github.com/vektah/gqlparser/v2 v2.5.6
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.34.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect
go.opentelemetry.io/contrib/instrumentation/runtime v0.34.0 go.opentelemetry.io/contrib/instrumentation/runtime v0.42.0 // indirect
go.opentelemetry.io/otel v1.9.0 go.opentelemetry.io/otel v1.16.0
go.opentelemetry.io/otel/exporters/prometheus v0.31.0 go.opentelemetry.io/otel/exporters/prometheus v0.39.0 // indirect
go.opentelemetry.io/otel/metric v0.31.0 go.opentelemetry.io/otel/metric v1.16.0
go.opentelemetry.io/otel/sdk v1.9.0 go.opentelemetry.io/otel/sdk v1.16.0 // indirect
go.opentelemetry.io/otel/sdk/metric v0.31.0 go.opentelemetry.io/otel/sdk/metric v0.39.0 // indirect
go.opentelemetry.io/otel/trace v1.9.0 go.opentelemetry.io/otel/trace v1.16.0
golang.org/x/sync v0.1.0 golang.org/x/sync v0.3.0 // indirect
) )
require github.com/tj/go-semver v1.0.0 require github.com/tj/go-semver v1.0.0
require github.com/patrickmn/go-cache v2.1.0+incompatible require (
github.com/patrickmn/go-cache v2.1.0+incompatible
go.sour.is/pkg v0.0.1
)
require ( require (
github.com/hashicorp/golang-lru/v2 v2.0.3 // indirect
github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect
github.com/taigrr/go-colorhash v0.0.0-20220329080504-742db7f45eae // indirect github.com/taigrr/go-colorhash v0.0.0-20220329080504-742db7f45eae // indirect
) )
@ -37,24 +40,20 @@ require (
github.com/agnivade/levenshtein v1.1.1 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect github.com/andybalholm/brotli v1.0.4 // indirect
github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect
github.com/beeker1121/goque v2.1.0+incompatible // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cyphar/filepath-securejoin v0.2.3 // indirect github.com/cyphar/filepath-securejoin v0.2.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
github.com/dchest/blake2b v1.0.0 // indirect github.com/dchest/blake2b v1.0.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/logr v1.2.4 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-cmp v0.5.9 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/jpillora/backoff v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect
github.com/keybase/go-codec v0.0.0-20180928230036-164397562123 // indirect github.com/keybase/go-codec v0.0.0-20180928230036-164397562123 // indirect
github.com/keybase/saltpack v0.0.0-20221220231257-f6cce11cfd0f // indirect github.com/keybase/saltpack v0.0.0-20221220231257-f6cce11cfd0f // indirect
@ -65,20 +64,15 @@ require (
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/oklog/ulid v1.3.1 github.com/oklog/ulid v1.3.1
github.com/onsi/ginkgo v1.14.0 // indirect
github.com/onsi/gomega v1.10.3 // indirect
github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d // indirect github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/posener/formatter v1.0.0 // indirect github.com/posener/formatter v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect
github.com/shirou/gopsutil/v3 v3.22.3 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/timewasted/go-accept-headers v0.0.0-20130320203746-c78f304b1b09 // indirect github.com/timewasted/go-accept-headers v0.0.0-20130320203746-c78f304b1b09 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
@ -86,31 +80,29 @@ require (
github.com/vmihailenco/tagparser v0.1.2 // indirect github.com/vmihailenco/tagparser v0.1.2 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/writeas/go-strip-markdown/v2 v2.1.1 // indirect github.com/writeas/go-strip-markdown/v2 v2.1.1 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.mills.io/salty v0.0.0-20220322161301-ce2b9f6573fa // indirect go.mills.io/salty v0.0.0-20220322161301-ce2b9f6573fa // indirect
go.opentelemetry.io/contrib v1.9.0 // indirect go.opentelemetry.io/contrib v1.16.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.9.0 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.9.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect
go.opentelemetry.io/proto/otlp v0.18.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.yarn.social/lextwt v0.0.0-20221221200320-31bca76a2587 // indirect go.yarn.social/lextwt v0.0.0-20221221200320-31bca76a2587 // indirect
go.yarn.social/types v0.0.0-20221027173319-2d00e96a95c1 // indirect go.yarn.social/types v0.0.0-20221027173319-2d00e96a95c1 // indirect
golang.org/x/crypto v0.5.0 // indirect golang.org/x/crypto v0.5.0 // indirect
golang.org/x/net v0.5.0 // indirect golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.4.0 // indirect golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.6.0 // indirect golang.org/x/text v0.9.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
google.golang.org/grpc v1.46.2 // indirect google.golang.org/grpc v1.55.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.30.0 // indirect
nhooyr.io/websocket v1.8.7 // indirect nhooyr.io/websocket v1.8.7 // indirect
) )
require ( require (
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
github.com/golang-jwt/jwt/v4 v4.4.3 github.com/golang-jwt/jwt/v4 v4.5.0
github.com/keys-pub/keys v0.1.22 github.com/keys-pub/keys v0.1.22
github.com/matryer/is v1.4.0 github.com/matryer/is v1.4.1
github.com/oklog/ulid/v2 v2.1.0 github.com/oklog/ulid/v2 v2.1.0
github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/gjson v1.14.4 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
@ -118,7 +110,7 @@ require (
github.com/tidwall/tinylru v1.1.0 // indirect github.com/tidwall/tinylru v1.1.0 // indirect
gitlab.com/jamietanna/content-negotiation-go v0.2.0 gitlab.com/jamietanna/content-negotiation-go v0.2.0
go.mills.io/saltyim v0.0.0-20230128070719-15a64de82829 go.mills.io/saltyim v0.0.0-20230128070719-15a64de82829
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.9.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 // indirect
go.uber.org/multierr v1.8.0 go.uber.org/multierr v1.11.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )

243
go.sum
View File

@ -36,10 +36,9 @@ git.mills.io/prologic/msgbus v0.1.20 h1:RWhuRgLRHkaWKqgBgpQQhgtFXQBXJjO7Fardu6kc
git.mills.io/prologic/msgbus v0.1.20/go.mod h1:ZFnDXoFvujU18Hv45pk0isCWAGjpkHpY9+/WSLzKJek= git.mills.io/prologic/msgbus v0.1.20/go.mod h1:ZFnDXoFvujU18Hv45pk0isCWAGjpkHpY9+/WSLzKJek=
git.mills.io/prologic/observe v0.0.0-20210712230028-fc31c7aa2bd1 h1:e6ZyAOFGLZJZYL2galNvfuNMqeQDdilmQ5WRBXCNL5s= git.mills.io/prologic/observe v0.0.0-20210712230028-fc31c7aa2bd1 h1:e6ZyAOFGLZJZYL2galNvfuNMqeQDdilmQ5WRBXCNL5s=
git.mills.io/prologic/useragent v0.0.0-20210714100044-d249fe7921a0 h1:MojWEgZyiugUbgyjydrdSAkHlADnbt90dXyURRYFzQ4= git.mills.io/prologic/useragent v0.0.0-20210714100044-d249fe7921a0 h1:MojWEgZyiugUbgyjydrdSAkHlADnbt90dXyURRYFzQ4=
github.com/99designs/gqlgen v0.17.13 h1:ETUEqvRg5Zvr1lXtpoRdj026fzVay0ZlJPwI33qXLIw= github.com/99designs/gqlgen v0.17.34 h1:5cS5/OKFguQt+Ws56uj9FlG2xm1IlcJWNF2jrMIKYFQ=
github.com/99designs/gqlgen v0.17.13/go.mod h1:w1brbeOdqVyNJI553BGwtwdVcYu1LKeYE1opLWN9RgQ= github.com/99designs/gqlgen v0.17.34/go.mod h1:Axcd3jIFHBVcqzixujJQr1wGqE+lGTpz6u4iZBZg1G8=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@ -47,7 +46,6 @@ github.com/ScaleFT/sshkeys v0.0.0-20200327173127-6142f742bca5/go.mod h1:gxOHeajF
github.com/ScaleFT/sshkeys v1.2.0 h1:5BRp6rTVIhJzXT3VcUQrKgXR8zWA3sOsNeuyW15WUA8= github.com/ScaleFT/sshkeys v1.2.0 h1:5BRp6rTVIhJzXT3VcUQrKgXR8zWA3sOsNeuyW15WUA8=
github.com/ScaleFT/sshkeys v1.2.0/go.mod h1:gxOHeajFfvGQh/fxlC8oOKBe23xnnJTif00IFFbiT+o= github.com/ScaleFT/sshkeys v1.2.0/go.mod h1:gxOHeajFfvGQh/fxlC8oOKBe23xnnJTif00IFFbiT+o=
github.com/abcum/lcp v0.0.0-20201209214815-7a3f3840be81 h1:uHogIJ9bXH75ZYrXnVShHIyywFiUZ7OOabwd9Sfd8rw= github.com/abcum/lcp v0.0.0-20201209214815-7a3f3840be81 h1:uHogIJ9bXH75ZYrXnVShHIyywFiUZ7OOabwd9Sfd8rw=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
@ -60,14 +58,11 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdK
github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/badgerodon/ioutil v0.0.0-20150716134133-06e58e34b867/go.mod h1:Ctq1YQi0dOq7QgBLZZ7p1Fr3IbAAqL/yMqDIHoe9WtE= github.com/badgerodon/ioutil v0.0.0-20150716134133-06e58e34b867/go.mod h1:Ctq1YQi0dOq7QgBLZZ7p1Fr3IbAAqL/yMqDIHoe9WtE=
github.com/beeker1121/goque v2.1.0+incompatible h1:m5pZ5b8nqzojS2DF2ioZphFYQUqGYsDORq6uefUItPM=
github.com/beeker1121/goque v2.1.0+incompatible/go.mod h1:L6dOWBhDOnxUVQsb0wkLve0VCnt2xJW/MI8pdRX4ANw=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@ -83,9 +78,7 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
@ -109,13 +102,10 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
@ -126,12 +116,10 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
@ -147,11 +135,11 @@ github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -178,11 +166,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -194,7 +180,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -226,9 +211,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru/v2 v2.0.3 h1:kmRrRLlInXvng0SmLxmQpQkpbYAvcXm7NPDrgxJa9mE=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.3/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
@ -239,7 +223,6 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/justinas/nosurf v1.1.1 h1:92Aw44hjSK4MxJeMSyDa7jwuI9GR2J/JCQiaKvXXSlk= github.com/justinas/nosurf v1.1.1 h1:92Aw44hjSK4MxJeMSyDa7jwuI9GR2J/JCQiaKvXXSlk=
github.com/kevinmbeaulieu/eq-go v1.0.0/go.mod h1:G3S8ajA56gKBZm4UB9AOyoOS37JO3roToPzKNM8dtdM=
github.com/keybase/go-codec v0.0.0-20180928230036-164397562123 h1:yg56lYPqh9suJepqxOMd/liFgU/x+maRPiB30JNYykM= github.com/keybase/go-codec v0.0.0-20180928230036-164397562123 h1:yg56lYPqh9suJepqxOMd/liFgU/x+maRPiB30JNYykM=
github.com/keybase/go-codec v0.0.0-20180928230036-164397562123/go.mod h1:r/eVVWCngg6TsFV/3HuS9sWhDkAzGG8mXhiuYA+Z/20= github.com/keybase/go-codec v0.0.0-20180928230036-164397562123/go.mod h1:r/eVVWCngg6TsFV/3HuS9sWhDkAzGG8mXhiuYA+Z/20=
github.com/keybase/go-keychain v0.0.0-20201121013009-976c83ec27a6/go.mod h1:N83iQ9rnnzi2KZuTu+0xBcD1JNWn1jSN140ggAF7HeE= github.com/keybase/go-keychain v0.0.0-20201121013009-976c83ec27a6/go.mod h1:N83iQ9rnnzi2KZuTu+0xBcD1JNWn1jSN140ggAF7HeE=
@ -256,8 +239,8 @@ github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7y
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -271,45 +254,25 @@ github.com/likexian/gokit v0.25.9 h1:rzSQ/dP7Qw+QUzSuWlrLF0AtZS3Di6uO5yWOKhx2Gk4
github.com/likexian/gokit v0.25.9/go.mod h1:oDDqJUcnnF9uAKuw54F7s6oEG+OJ7eallfDW2dq0A/o= github.com/likexian/gokit v0.25.9/go.mod h1:oDDqJUcnnF9uAKuw54F7s6oEG+OJ7eallfDW2dq0A/o=
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc= github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
github.com/logzio/logzio-go v1.0.6 h1:BIVu5TWDZc0vlEkwSDjoxPlV/aMJV2LdM3k+CjdzFDg= github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/logzio/logzio-go v1.0.6/go.mod h1:ljlI3Zfi3hntJiHqCqWSUPT9cZP6yvDHUzDl5ZLGYRE=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/maxence-charriere/go-app/v9 v9.4.1 h1:uDrMIvjzkXwBjw5594i7ZqD5LY5iN7j1KeMImjWAYiw= github.com/maxence-charriere/go-app/v9 v9.4.1 h1:uDrMIvjzkXwBjw5594i7ZqD5LY5iN7j1KeMImjWAYiw=
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mlctrez/goapp-mdc v0.2.6 h1:/nSRAqC3xz+GFCd3Zl3yI87bBeEpJVXi5FSMnRighXo= github.com/mlctrez/goapp-mdc v0.2.6 h1:/nSRAqC3xz+GFCd3Zl3yI87bBeEpJVXi5FSMnRighXo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/nullrocks/identicon v0.0.0-20180626043057-7875f45b0022 h1:Ys0rDzh8s4UMlGaDa1UTA0sfKgvF0hQZzTYX8ktjiDc= github.com/nullrocks/identicon v0.0.0-20180626043057-7875f45b0022 h1:Ys0rDzh8s4UMlGaDa1UTA0sfKgvF0hQZzTYX8ktjiDc=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
@ -324,34 +287,29 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/formatter v1.0.0 h1:TwXJq26f9ERTjCpZj8xEWj77WPWfX/nBgGx52Ap/gYM= github.com/posener/formatter v1.0.0 h1:TwXJq26f9ERTjCpZj8xEWj77WPWfX/nBgGx52Ap/gYM=
github.com/posener/formatter v1.0.0/go.mod h1:xrC89js6vw5dde/9yUKKU9MY5ivn980yX4VG7gYQTvU= github.com/posener/formatter v1.0.0/go.mod h1:xrC89js6vw5dde/9yUKKU9MY5ivn980yX4VG7gYQTvU=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/ravilushqa/otelgqlgen v0.9.0 h1:NgbrU9OHPKB/X6Ja618+SqPNls05M3T8aV1fkUiR9ow= github.com/ravilushqa/otelgqlgen v0.13.1 h1:V+zFE75iDd2/CSzy5kKnb+Fi09SsE5535wv9U2nUEFE=
github.com/ravilushqa/otelgqlgen v0.9.0/go.mod h1:TqSvbt/7E23CHOOgL6G+42kCbhvxUpT/21tMsarq4Hk= github.com/ravilushqa/otelgqlgen v0.13.1/go.mod h1:ZIyWykK2paCuNi9k8gk5edcNSwDJuxZaW90vZXpafxw=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0=
github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/shirou/gopsutil/v3 v3.22.3 h1:UebRzEomgMpv61e3hgD1tGooqX5trFbdU/ehphbHd00=
github.com/shirou/gopsutil/v3 v3.22.3/go.mod h1:D01hZJ4pVHPpCTZ3m3T2+wDF2YAGfd+H4ifUguaQzHM=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@ -362,10 +320,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/taigrr/go-colorhash v0.0.0-20220329080504-742db7f45eae h1:RXzKJmV0lGvBpY8/43bJShhPYIssF7X18UVMs9KIgIQ= github.com/taigrr/go-colorhash v0.0.0-20220329080504-742db7f45eae h1:RXzKJmV0lGvBpY8/43bJShhPYIssF7X18UVMs9KIgIQ=
github.com/taigrr/go-colorhash v0.0.0-20220329080504-742db7f45eae/go.mod h1:1xBq06Fnn6nvsoWc+BCWwFvC0Zx04/FA3mpq937vlyI= github.com/taigrr/go-colorhash v0.0.0-20220329080504-742db7f45eae/go.mod h1:1xBq06Fnn6nvsoWc+BCWwFvC0Zx04/FA3mpq937vlyI=
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
@ -386,8 +341,6 @@ github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160 h1:NSWpaDaurcAJY7PkL8Xt0
github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
github.com/tj/go-semver v1.0.0 h1:vpn6Jmn6Hi3QSmrP1PzYcqScop9IZiGCVOSn18wzu8w= github.com/tj/go-semver v1.0.0 h1:vpn6Jmn6Hi3QSmrP1PzYcqScop9IZiGCVOSn18wzu8w=
github.com/tj/go-semver v1.0.0/go.mod h1:YZuwVc013rh7KDV0k6tPbWrFeEHBHcp8amfJL+nHzjM= github.com/tj/go-semver v1.0.0/go.mod h1:YZuwVc013rh7KDV0k6tPbWrFeEHBHcp8amfJL+nHzjM=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
@ -396,10 +349,8 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/unrolled/logger v0.0.0-20201216141554-31a3694fe979 h1:47+K4wN0S8L3fUwgZtPEBIfNqtAE3tUvBfvHVZJAXfg= github.com/unrolled/logger v0.0.0-20201216141554-31a3694fe979 h1:47+K4wN0S8L3fUwgZtPEBIfNqtAE3tUvBfvHVZJAXfg=
github.com/unrolled/render v1.4.1 h1:VdpMc2YkAOWzbmC/P2yoHhRDXgsaCQHcTJ1KK6SNCA4= github.com/unrolled/render v1.4.1 h1:VdpMc2YkAOWzbmC/P2yoHhRDXgsaCQHcTJ1KK6SNCA4=
github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY= github.com/vektah/gqlparser/v2 v2.5.6 h1:Ou14T0N1s191eRMZ1gARVqohcbe1e8FrcONScsq8cRU=
github.com/vektah/gqlparser/v2 v2.4.6/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0= github.com/vektah/gqlparser/v2 v2.5.6/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME=
github.com/vektah/gqlparser/v2 v2.4.7 h1:yub2WLoSIr+chP1zMv6bjrsgTasfubxGZJeC8ISEpgE=
github.com/vektah/gqlparser/v2 v2.4.7/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0=
github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
@ -411,14 +362,10 @@ github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAh
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/writeas/go-strip-markdown/v2 v2.1.1 h1:hAxUM21Uhznf/FnbVGiJciqzska6iLei22Ijc3q2e28= github.com/writeas/go-strip-markdown/v2 v2.1.1 h1:hAxUM21Uhznf/FnbVGiJciqzska6iLei22Ijc3q2e28=
github.com/writeas/go-strip-markdown/v2 v2.1.1/go.mod h1:UvvgPJgn1vvN8nWuE5e7v/+qmDu3BSVnKAB6Gl7hFzA= github.com/writeas/go-strip-markdown/v2 v2.1.1/go.mod h1:UvvgPJgn1vvN8nWuE5e7v/+qmDu3BSVnKAB6Gl7hFzA=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
gitlab.com/jamietanna/content-negotiation-go v0.2.0 h1:vT0OLEPQ6DYRG3/1F7joXSNjVQHGivJ6+JzODlJfjWw= gitlab.com/jamietanna/content-negotiation-go v0.2.0 h1:vT0OLEPQ6DYRG3/1F7joXSNjVQHGivJ6+JzODlJfjWw=
gitlab.com/jamietanna/content-negotiation-go v0.2.0/go.mod h1:n4ZZ8/X5TstnjYRnjEtR/fC7MCTe+aRKM7PQlLBH3PQ= gitlab.com/jamietanna/content-negotiation-go v0.2.0/go.mod h1:n4ZZ8/X5TstnjYRnjEtR/fC7MCTe+aRKM7PQlLBH3PQ=
go.mills.io/salty v0.0.0-20220322161301-ce2b9f6573fa h1:KBxzYJMWP7MXd72RgqsMCGOSEqV6aaDDSdSb8usJCzQ= go.mills.io/salty v0.0.0-20220322161301-ce2b9f6573fa h1:KBxzYJMWP7MXd72RgqsMCGOSEqV6aaDDSdSb8usJCzQ=
@ -430,38 +377,37 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/contrib v1.9.0 h1:2KAoCVu4OMI9TYoSWvcV7+UbbIPOi4623S77nV+M/Ks= go.opentelemetry.io/contrib v1.16.1 h1:EpASvVyGx6/ZTlmXzxYfTMZxHROelCeXXa2uLiwltcs=
go.opentelemetry.io/contrib v1.9.0/go.mod h1:yp0N4+hnpWCpnMzs6T6WbD9Amfg7reEZsS0jAd/5M2Q= go.opentelemetry.io/contrib v1.16.1/go.mod h1:gIzjwWFoGazJmtCaDgViqOSJPde2mCWzv60o0bWPcZs=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.34.0 h1:9NkMW03wwEzPtP/KciZ4Ozu/Uz5ZA7kfqXJIObnrjGU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 h1:pginetY7+onl4qN1vl0xW/V/v6OBZ0vVdH+esuJgvmM=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.34.0/go.mod h1:548ZsYzmT4PL4zWKRd8q/N4z0Wxzn/ZxUE+lkEpwWQA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0/go.mod h1:XiYsayHc36K3EByOO6nbAXnAWbrUxdjUROCEeeROOH8=
go.opentelemetry.io/contrib/instrumentation/runtime v0.34.0 h1:zt4RDodWkgiHk8tyUmFOjFoOOfyGH7vwIbUzKP6CCh8= go.opentelemetry.io/contrib/instrumentation/runtime v0.42.0 h1:EbmAUG9hEAMXyfWEasIt2kmh/WmXUznUksChApTgBGc=
go.opentelemetry.io/contrib/instrumentation/runtime v0.34.0/go.mod h1:5wIoZE96WbcQVU3D6UF/ukRfFQXbB6OYgeWi9CjHa90= go.opentelemetry.io/contrib/instrumentation/runtime v0.42.0/go.mod h1:rD9feqRYP24P14t5kmhNMqsqm1jvKmpx2H2rKVw52V8=
go.opentelemetry.io/otel v1.9.0 h1:8WZNQFIB2a71LnANS9JeyidJKKGOOremcUtb/OtHISw= go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
go.opentelemetry.io/otel v1.9.0/go.mod h1:np4EoPGzoPs3O67xUVNoPPcmSvsfOxNlNA4F4AC+0Eo= go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.9.0 h1:ggqApEjDKczicksfvZUCxuvoyDmR6Sbm56LwiK8DVR0= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.9.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.9.0 h1:NN90Cuna0CnBg8YNu1Q0V35i2E8LDByFOwHRCq/ZP9I= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.9.0/go.mod h1:0EsCXjZAiiZGnLdEUXM9YjCKuuLZMYyglh2QDXcYKVA= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.9.0 h1:FAF9l8Wjxi9Ad2k/vLTfHZyzXYX72C62wBGpV3G6AIo= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 h1:iqjq9LAB8aK++sKVcELezzn655JnBNdsDhghU4G/So8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.9.0/go.mod h1:smUdtylgc0YQiUr2PuifS4hBXhAS5xtR6WQhxP1wiNA= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0/go.mod h1:hGXzO5bhhSHZnKvrDaXB82Y9DRFour0Nz/KrBh7reWw=
go.opentelemetry.io/otel/exporters/prometheus v0.31.0 h1:jwtnOGBM8dIty5AVZ+9ZCzZexCea3aVKmUfZAQcHqxs= go.opentelemetry.io/otel/exporters/prometheus v0.39.0 h1:whAaiHxOatgtKd+w0dOi//1KUxj3KoPINZdtDaDj3IA=
go.opentelemetry.io/otel/exporters/prometheus v0.31.0/go.mod h1:QarXIB8L79IwIPoNgG3A6zNvBgVmcppeFogV1d8612s= go.opentelemetry.io/otel/exporters/prometheus v0.39.0/go.mod h1:4jo5Q4CROlCpSPsXLhymi+LYrDXd2ObU5wbKayfZs7Y=
go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/sdk v1.9.0 h1:LNXp1vrr83fNXTHgU8eO89mhzxb/bbWAsHG6fNf3qWo= go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
go.opentelemetry.io/otel/sdk v1.9.0/go.mod h1:AEZc8nt5bd2F7BC24J5R0mrjYnpEgYHyTcM/vrSple4= go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4=
go.opentelemetry.io/otel/sdk/metric v0.31.0 h1:2sZx4R43ZMhJdteKAlKoHvRgrMp53V1aRxvEf5lCq8Q= go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI=
go.opentelemetry.io/otel/sdk/metric v0.31.0/go.mod h1:fl0SmNnX9mN9xgU6OLYLMBMrNAsaZQi7qBwprwO3abk= go.opentelemetry.io/otel/sdk/metric v0.39.0/go.mod h1:piDIRgjcK7u0HCL5pCA4e74qpK/jk3NiUoAHATVAmiI=
go.opentelemetry.io/otel/trace v1.9.0 h1:oZaCNJUjWcg60VXWee8lJKlqhPbXAPB51URuR47pQYc= go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
go.opentelemetry.io/otel/trace v1.9.0/go.mod h1:2737Q0MuG8q1uILYm2YYVkAyLtOofiTNGg6VODnOiPo= go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.18.0 h1:W5hyXNComRa23tGpKwG+FRAc4rfF6ZUg1JReK+QHS80= go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
go.opentelemetry.io/proto/otlp v0.18.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.sour.is/pkg v0.0.1 h1:wajjul3FNTljfcsNqNHsnelyVvsq8buuKrfxncJDuu0=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.sour.is/pkg v0.0.1/go.mod h1:jOdxxKILf+kXQmk1cG3sN4Ogxk8C4/14mxhy/QEJjv4=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.yarn.social/lextwt v0.0.0-20221221200320-31bca76a2587 h1:MuJTXSxPUNxqzT+q+fulCjkivDeC5jjZ7TSsf/f/24M= go.yarn.social/lextwt v0.0.0-20221221200320-31bca76a2587 h1:MuJTXSxPUNxqzT+q+fulCjkivDeC5jjZ7TSsf/f/24M=
go.yarn.social/lextwt v0.0.0-20221221200320-31bca76a2587/go.mod h1:XcveSVLWxkBBW32VEAnewBcnEYw8O2Vb/xqJmXC54Hs= go.yarn.social/lextwt v0.0.0-20221221200320-31bca76a2587/go.mod h1:XcveSVLWxkBBW32VEAnewBcnEYw8O2Vb/xqJmXC54Hs=
go.yarn.social/types v0.0.0-20221025190911-9524f5b4a743/go.mod h1:XN+G4HprNn/Gp7OF2zveqsCRSWFCHtOaIRh2GlcK+U4= go.yarn.social/types v0.0.0-20221025190911-9524f5b4a743/go.mod h1:XN+G4HprNn/Gp7OF2zveqsCRSWFCHtOaIRh2GlcK+U4=
@ -510,12 +456,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -537,21 +480,17 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -568,10 +507,9 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -580,11 +518,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -600,44 +534,34 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -681,13 +605,10 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@ -743,8 +664,9 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA=
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@ -761,8 +683,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ= google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -776,24 +698,17 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
package generated

View File

@ -5,11 +5,12 @@ package resolver
import ( import (
"context" "context"
"go.sour.is/pkg/gql"
"go.sour.is/ev/app/msgbus" "go.sour.is/ev/app/msgbus"
"go.sour.is/ev/app/salty" "go.sour.is/ev/app/salty"
"go.sour.is/ev/internal/graph/generated" "go.sour.is/ev/internal/graph/generated"
"go.sour.is/ev/pkg/es" "go.sour.is/ev/pkg/es"
"go.sour.is/ev/pkg/gql"
) )
type Resolver struct{} type Resolver struct{}

View File

@ -1,68 +0,0 @@
package lg
import (
"context"
"log"
"os"
"strings"
"go.uber.org/multierr"
)
func Init(ctx context.Context, name string) (context.Context, func(context.Context) error) {
ctx, span := Span(ctx)
defer span.End()
stop := [3]func() error{
initLogger(name),
}
ctx, stop[1] = initMetrics(ctx, name)
ctx, stop[2] = initTracing(ctx, name)
reverse(stop[:])
return ctx, func(context.Context) error {
log.Println("flushing logs...")
errs := make([]error, len(stop))
for i, fn := range stop {
if fn != nil {
errs[i] = fn()
}
}
log.Println("all stopped.")
return multierr.Combine(errs...)
}
}
func env(name, defaultValue string) string {
name = strings.TrimSpace(name)
defaultValue = strings.TrimSpace(defaultValue)
if v := strings.TrimSpace(os.Getenv(name)); v != "" {
log.Println("# ", name, "=", v)
return v
}
log.Println("# ", name, "=", defaultValue, "(default)")
return defaultValue
}
type secret string
func (s secret) String() string {
if s == "" {
return "(nil)"
}
return "***"
}
func (s secret) Secret() string {
return string(s)
}
func envSecret(name, defaultValue string) secret {
name = strings.TrimSpace(name)
defaultValue = strings.TrimSpace(defaultValue)
if v := strings.TrimSpace(os.Getenv(name)); v != "" {
log.Println("# ", name, "=", secret(v))
return secret(v)
}
log.Println("# ", name, "=", secret(defaultValue), "(default)")
return secret(defaultValue)
}

View File

@ -1,111 +0,0 @@
package lg
import (
"bytes"
"encoding/json"
"io"
"log"
"os"
"runtime/debug"
"strings"
"time"
"github.com/go-logr/stdr"
"github.com/logzio/logzio-go"
"go.opentelemetry.io/otel"
)
type logzwriter struct {
name string
pkg string
goversion string
hostname string
w io.Writer
}
func (l *logzwriter) Write(b []byte) (int, error) {
i := 0
for _, sp := range bytes.Split(b, []byte("\n")) {
msg := struct {
Message string `json:"message"`
Host string `json:"host"`
GoVersion string `json:"go_version"`
Package string `json:"pkg"`
App string `json:"app"`
}{
Message: strings.TrimSpace(string(sp)),
Host: l.hostname,
GoVersion: l.goversion,
Package: l.pkg,
App: l.name,
}
if msg.Message == "" || strings.HasPrefix(msg.Message, "#") {
continue
}
b, err := json.Marshal(msg)
if err != nil {
return 0, err
}
j, err := l.w.Write(b)
i += j
if err != nil {
return i, err
}
}
return i, nil
}
func initLogger(name string) func() error {
log.SetPrefix("[" + name + "] ")
log.SetFlags(log.LstdFlags&^(log.Ldate|log.Ltime) | log.Lshortfile)
token := envSecret("LOGZIO_LOG_TOKEN", "")
if token == "" {
return nil
}
l, err := logzio.New(
token.Secret(),
// logzio.SetDebug(os.Stderr),
logzio.SetUrl(env("LOGZIO_LOG_URL", "https://listener.lg.io:8071")),
logzio.SetDrainDuration(time.Second*5),
logzio.SetTempDirectory(env("LOGZIO_DIR", os.TempDir())),
logzio.SetCheckDiskSpace(true),
logzio.SetDrainDiskThreshold(70),
)
if err != nil {
return nil
}
w := io.MultiWriter(os.Stderr, lzw(l, name))
log.SetOutput(w)
otel.SetLogger(stdr.New(log.Default()))
return func() error {
defer log.Println("logger stopped")
log.SetOutput(os.Stderr)
l.Stop()
return nil
}
}
func lzw(l io.Writer, name string) io.Writer {
lz := &logzwriter{
name: name,
w: l,
}
if info, ok := debug.ReadBuildInfo(); ok {
lz.goversion = info.GoVersion
lz.pkg = info.Path
}
if hostname, err := os.Hostname(); err == nil {
lz.hostname = hostname
}
return lz
}

View File

@ -1,103 +0,0 @@
package lg
import (
"context"
"log"
"net/http"
"os"
"runtime/debug"
"time"
"go.opentelemetry.io/contrib/instrumentation/runtime"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/global"
"go.opentelemetry.io/otel/sdk/metric/aggregator/histogram"
controller "go.opentelemetry.io/otel/sdk/metric/controller/basic"
"go.opentelemetry.io/otel/sdk/metric/export/aggregation"
processor "go.opentelemetry.io/otel/sdk/metric/processor/basic"
selector "go.opentelemetry.io/otel/sdk/metric/selector/simple"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)
var meterKey = contextKey{"meter"}
var promHTTPKey = contextKey{"promHTTP"}
func Meter(ctx context.Context) metric.Meter {
if t := fromContext[contextKey, metric.Meter](ctx, tracerKey); t != nil {
return t
}
return global.Meter("")
}
func NewHTTP(ctx context.Context) *httpHandle {
t := fromContext[contextKey, *prometheus.Exporter](ctx, promHTTPKey)
return &httpHandle{t}
}
func initMetrics(ctx context.Context, name string) (context.Context, func() error) {
goversion := ""
pkg := ""
host := ""
if info, ok := debug.ReadBuildInfo(); ok {
goversion = info.GoVersion
pkg = info.Path
}
if h, err := os.Hostname(); err == nil {
host = h
}
config := prometheus.Config{
DefaultHistogramBoundaries: []float64{
2 << 6, 2 << 8, 2 << 10, 2 << 12, 2 << 14, 2 << 16, 2 << 18, 2 << 20, 2 << 22, 2 << 24, 2 << 26, 2 << 28,
},
}
cont := controller.New(
processor.NewFactory(
selector.NewWithHistogramDistribution(
histogram.WithExplicitBoundaries(config.DefaultHistogramBoundaries),
),
aggregation.CumulativeTemporalitySelector(),
processor.WithMemory(true),
),
controller.WithResource(
resource.NewWithAttributes(
semconv.SchemaURL,
attribute.String("app", name),
attribute.String("host", host),
attribute.String("go_version", goversion),
attribute.String("pkg", pkg),
),
),
)
ex, err := prometheus.New(config, cont)
if err != nil {
return ctx, nil
}
ctx = toContext(ctx, promHTTPKey, ex)
global.SetMeterProvider(cont)
m := cont.Meter(name)
ctx = toContext(ctx, meterKey, m)
runtime.Start()
return ctx, func() error {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
defer log.Println("metrics stopped")
return cont.Stop(ctx)
}
}
type httpHandle struct {
exp *prometheus.Exporter
}
func (h *httpHandle) RegisterHTTP(mux *http.ServeMux) {
if h.exp == nil {
return
}
mux.Handle("/metrics", h.exp)
}

View File

@ -1,176 +0,0 @@
package lg
import (
"context"
"fmt"
"log"
"net/http"
"runtime"
"strconv"
"time"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
"go.opentelemetry.io/otel/trace"
)
type contextKey struct {
name string
}
var tracerKey = contextKey{"tracer"}
func Tracer(ctx context.Context) trace.Tracer {
if t := fromContext[contextKey, trace.Tracer](ctx, tracerKey); t != nil {
return t
}
return otel.Tracer("")
}
func attrs(ctx context.Context) (string, []attribute.KeyValue) {
var attrs []attribute.KeyValue
var name string
if pc, file, line, ok := runtime.Caller(2); ok {
if fn := runtime.FuncForPC(pc); fn != nil {
name = fn.Name()
}
attrs = append(attrs,
attribute.String("pc", fmt.Sprintf("%v", pc)),
attribute.String("file", file),
attribute.Int("line", line),
)
}
return name, attrs
}
func Span(ctx context.Context, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
name, attrs := attrs(ctx)
attrs = append(attrs, attribute.String("name", name))
ctx, span := Tracer(ctx).Start(ctx, name, opts...)
span.SetAttributes(attrs...)
return ctx, span
}
func NamedSpan(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
_, attrs := attrs(ctx)
attrs = append(attrs, attribute.String("name", name))
ctx, span := Tracer(ctx).Start(ctx, name, opts...)
span.SetAttributes(attrs...)
return ctx, span
}
func Fork(ctx context.Context, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
name, attrs := attrs(ctx)
childCTX, childSpan := Tracer(ctx).Start(context.Background(), name, append(opts, trace.WithLinks(trace.LinkFromContext(ctx)))...)
childSpan.SetAttributes(attrs...)
_, span := Tracer(ctx).Start(ctx, name, append(opts, trace.WithLinks(trace.LinkFromContext(childCTX)))...)
span.SetAttributes(attrs...)
defer span.End()
return childCTX, childSpan
}
type SampleRate string
const (
SampleAlways SampleRate = "always"
SampleNever SampleRate = "never"
)
func initTracing(ctx context.Context, name string) (context.Context, func() error) {
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceNameKey.String(name),
),
)
if err != nil {
log.Println(wrap(err, "failed to create trace resource"))
return ctx, nil
}
exporterAddr := env("EV_TRACE_ENDPOINT", "")
if exporterAddr == "" {
return ctx, nil
}
traceExporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithInsecure(),
otlptracehttp.WithEndpoint(exporterAddr),
)
if err != nil {
log.Println(wrap(err, "failed to create trace exporter"))
return ctx, nil
}
bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
var sample sdktrace.TracerProviderOption
sampleRate := SampleRate(env("EV_TRACE_SAMPLE", string(SampleNever)))
switch sampleRate {
case "always":
sample = sdktrace.WithSampler(sdktrace.AlwaysSample())
case "never":
sample = sdktrace.WithSampler(sdktrace.NeverSample())
default:
if v, err := strconv.Atoi(string(sampleRate)); err != nil {
sample = sdktrace.WithSampler(sdktrace.NeverSample())
} else {
sample = sdktrace.WithSampler(sdktrace.TraceIDRatioBased(float64(v) * 0.01))
}
}
tracerProvider := sdktrace.NewTracerProvider(
sample,
sdktrace.WithResource(res),
sdktrace.WithSpanProcessor(bsp),
)
otel.SetTracerProvider(tracerProvider)
otel.SetTextMapPropagator(propagation.TraceContext{})
ctx = toContext(ctx, tracerKey, otel.Tracer(name))
return ctx, func() error {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
defer log.Println("tracer stopped")
return wrap(tracerProvider.Shutdown(ctx), "failed to shutdown TracerProvider")
}
}
func wrap(err error, s string) error {
if err != nil {
return fmt.Errorf(s, err)
}
return nil
}
func reverse[T any](s []T) {
first, last := 0, len(s)-1
for first < last {
s[first], s[last] = s[last], s[first]
first++
last--
}
}
func Htrace(h http.Handler, name string) http.Handler {
return otelhttp.NewHandler(h, name, otelhttp.WithSpanNameFormatter(func(operation string, r *http.Request) string {
return fmt.Sprintf("%s: %s", operation, r.RequestURI)
}))
}
func toContext[K comparable, V any](ctx context.Context, key K, value V) context.Context {
return context.WithValue(ctx, key, value)
}
func fromContext[K comparable, V any](ctx context.Context, key K) V {
var empty V
if v, ok := ctx.Value(key).(V); ok {
return v
}
return empty
}

View File

@ -1,131 +0,0 @@
package authreq
import (
"bytes"
"context"
"crypto/ed25519"
"encoding/base64"
"fmt"
"hash/fnv"
"io"
"net/http"
"strings"
"time"
"github.com/golang-jwt/jwt/v4"
)
var SignatureLifetime = 30 * time.Minute
var AuthHeader = "Authorization"
func Sign(req *http.Request, key ed25519.PrivateKey) (*http.Request, error) {
pub := enc([]byte(key.Public().(ed25519.PublicKey)))
h := fnv.New128a()
fmt.Fprint(h, req.Method, req.URL.String())
if req.Body != nil {
b := &bytes.Buffer{}
w := io.MultiWriter(h, b)
_, err := io.Copy(w, req.Body)
if err != nil {
return req, err
}
req.Body = io.NopCloser(b)
}
token := jwt.NewWithClaims(jwt.SigningMethodEdDSA, jwt.RegisteredClaims{
Subject: enc(h.Sum(nil)),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(SignatureLifetime)),
IssuedAt: jwt.NewNumericDate(time.Now()),
Issuer: pub,
})
sig, err := token.SignedString(key)
if err != nil {
return req, err
}
req.Header.Set(AuthHeader, sig)
return req, nil
}
func Authorization(hdlr http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
auth := req.Header.Get(AuthHeader)
if auth == "" {
rw.WriteHeader(http.StatusUnauthorized)
return
}
h := fnv.New128a()
fmt.Fprint(h, req.Method, req.URL.String())
if req.Body != nil {
b := &bytes.Buffer{}
w := io.MultiWriter(h, b)
_, err := io.Copy(w, req.Body)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
}
}
subject := enc(h.Sum(nil))
token, err := jwt.ParseWithClaims(
string(auth),
&jwt.RegisteredClaims{},
func(tok *jwt.Token) (any, error) {
c, ok := tok.Claims.(*jwt.RegisteredClaims)
if !ok {
return nil, fmt.Errorf("wrong type of claim")
}
pub, err := dec(c.Issuer)
return ed25519.PublicKey(pub), err
},
jwt.WithValidMethods([]string{jwt.SigningMethodEdDSA.Alg()}),
jwt.WithJSONNumber(),
)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
return
}
c, ok := token.Claims.(*jwt.RegisteredClaims)
if !ok {
rw.WriteHeader(http.StatusUnprocessableEntity)
return
}
req = req.WithContext(context.WithValue(req.Context(), contextKey, c))
if c.Subject != subject {
rw.WriteHeader(http.StatusForbidden)
return
}
hdlr.ServeHTTP(rw, req)
})
}
func enc(b []byte) string {
return base64.RawURLEncoding.EncodeToString(b)
}
func dec(s string) ([]byte, error) {
s = strings.TrimSpace(s)
return base64.RawURLEncoding.DecodeString(s)
}
var contextKey = struct{ name string }{"jwtClaim"}
func FromContext(ctx context.Context) *jwt.RegisteredClaims {
if v := ctx.Value(contextKey); v != nil {
if c, ok := v.(*jwt.RegisteredClaims); ok {
return c
}
}
return nil
}

View File

@ -1,104 +0,0 @@
package authreq_test
import (
"crypto/ed25519"
"encoding/base64"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/matryer/is"
"go.sour.is/ev/pkg/authreq"
)
func TestGETRequest(t *testing.T) {
is := is.New(t)
pub, priv, err := ed25519.GenerateKey(nil)
is.NoErr(err)
req, err := http.NewRequest(http.MethodGet, "http://example.com/"+enc(pub)+"/test?q=test", nil)
is.NoErr(err)
req, err = authreq.Sign(req, priv)
is.NoErr(err)
t.Log(enc(pub))
t.Log(req.Header.Get(authreq.AuthHeader))
var hdlr http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c := authreq.FromContext(r.Context())
if c == nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
if !strings.Contains(req.URL.Path, c.Issuer) {
w.WriteHeader(http.StatusForbidden)
return
}
})
hdlr = authreq.Authorization(hdlr)
rw := httptest.NewRecorder()
hdlr.ServeHTTP(rw, req)
is.Equal(rw.Code, http.StatusOK)
}
func TestPOSTRequest(t *testing.T) {
is := is.New(t)
content := "this is post!"
pub, priv, err := ed25519.GenerateKey(nil)
is.NoErr(err)
req, err := http.NewRequest(http.MethodPost, "http://example.com/"+enc(pub)+"/test?q=test", strings.NewReader(content))
is.NoErr(err)
req, err = authreq.Sign(req, priv)
is.NoErr(err)
t.Log(enc(pub))
t.Log(req.Header.Get(authreq.AuthHeader))
var hdlr http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c := authreq.FromContext(r.Context())
if c == nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
contentCheck, err := io.ReadAll(r.Body)
r.Body.Close()
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
t.Log(string(contentCheck))
if !strings.Contains(req.URL.Path, c.Issuer) {
w.WriteHeader(http.StatusForbidden)
return
}
})
hdlr = authreq.Authorization(hdlr)
rw := httptest.NewRecorder()
hdlr.ServeHTTP(rw, req)
is.Equal(rw.Code, http.StatusOK)
}
func enc(b []byte) string {
return base64.RawURLEncoding.EncodeToString(b)
}

238
pkg/cache/cache.go vendored
View File

@ -1,238 +0,0 @@
package cache
import (
"context"
"sync"
)
const (
// DefaultEvictedBufferSize defines the default buffer size to store evicted key/val
DefaultEvictedBufferSize = 16
)
// Cache is a thread-safe fixed size LRU cache.
type Cache[K comparable, V any] struct {
lru *LRU[K, V]
evictedKeys []K
evictedVals []V
onEvictedCB func(ctx context.Context, k K, v V)
lock sync.RWMutex
}
// New creates an LRU of the given size.
func NewCache[K comparable, V any](size int) (*Cache[K, V], error) {
return NewWithEvict[K, V](size, nil)
}
// NewWithEvict constructs a fixed size cache with the given eviction
// callback.
func NewWithEvict[K comparable, V any](size int, onEvicted func(context.Context, K, V)) (c *Cache[K, V], err error) {
// create a cache with default settings
c = &Cache[K, V]{
onEvictedCB: onEvicted,
}
if onEvicted != nil {
c.initEvictBuffers()
onEvicted = c.onEvicted
}
c.lru, err = NewLRU(size, onEvicted)
return
}
func (c *Cache[K, V]) initEvictBuffers() {
c.evictedKeys = make([]K, 0, DefaultEvictedBufferSize)
c.evictedVals = make([]V, 0, DefaultEvictedBufferSize)
}
// onEvicted save evicted key/val and sent in externally registered callback
// outside of critical section
func (c *Cache[K, V]) onEvicted(ctx context.Context, k K, v V) {
c.evictedKeys = append(c.evictedKeys, k)
c.evictedVals = append(c.evictedVals, v)
}
// Purge is used to completely clear the cache.
func (c *Cache[K, V]) Purge(ctx context.Context) {
var ks []K
var vs []V
c.lock.Lock()
c.lru.Purge(ctx)
if c.onEvictedCB != nil && len(c.evictedKeys) > 0 {
ks, vs = c.evictedKeys, c.evictedVals
c.initEvictBuffers()
}
c.lock.Unlock()
// invoke callback outside of critical section
if c.onEvictedCB != nil {
for i := 0; i < len(ks); i++ {
c.onEvictedCB(ctx, ks[i], vs[i])
}
}
}
// Add adds a value to the cache. Returns true if an eviction occurred.
func (c *Cache[K, V]) Add(ctx context.Context, key K, value V) (evicted bool) {
var k K
var v V
c.lock.Lock()
evicted = c.lru.Add(ctx, key, value)
if c.onEvictedCB != nil && evicted {
k, v = c.evictedKeys[0], c.evictedVals[0]
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
}
c.lock.Unlock()
if c.onEvictedCB != nil && evicted {
c.onEvictedCB(ctx, k, v)
}
return
}
// Get looks up a key's value from the cache.
func (c *Cache[K, V]) Get(key K) (value *V, ok bool) {
c.lock.Lock()
value, ok = c.lru.Get(key)
c.lock.Unlock()
return value, ok
}
// Contains checks if a key is in the cache, without updating the
// recent-ness or deleting it for being stale.
func (c *Cache[K, V]) Contains(key K) bool {
c.lock.RLock()
containKey := c.lru.Contains(key)
c.lock.RUnlock()
return containKey
}
// Peek returns the key value (or undefined if not found) without updating
// the "recently used"-ness of the key.
func (c *Cache[K, V]) Peek(key K) (value *V, ok bool) {
c.lock.RLock()
value, ok = c.lru.Peek(key)
c.lock.RUnlock()
return value, ok
}
// ContainsOrAdd checks if a key is in the cache without updating the
// recent-ness or deleting it for being stale, and if not, adds the value.
// Returns whether found and whether an eviction occurred.
func (c *Cache[K, V]) ContainsOrAdd(ctx context.Context, key K, value V) (ok, evicted bool) {
var k K
var v V
c.lock.Lock()
if c.lru.Contains(key) {
c.lock.Unlock()
return true, false
}
evicted = c.lru.Add(ctx, key, value)
if c.onEvictedCB != nil && evicted {
k, v = c.evictedKeys[0], c.evictedVals[0]
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
}
c.lock.Unlock()
if c.onEvictedCB != nil && evicted {
c.onEvictedCB(ctx, k, v)
}
return false, evicted
}
// PeekOrAdd checks if a key is in the cache without updating the
// recent-ness or deleting it for being stale, and if not, adds the value.
// Returns whether found and whether an eviction occurred.
func (c *Cache[K, V]) PeekOrAdd(ctx context.Context, key K, value V) (previous *V, ok, evicted bool) {
var k K
var v V
c.lock.Lock()
previous, ok = c.lru.Peek(key)
if ok {
c.lock.Unlock()
return previous, true, false
}
evicted = c.lru.Add(ctx, key, value)
if c.onEvictedCB != nil && evicted {
k, v = c.evictedKeys[0], c.evictedVals[0]
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
}
c.lock.Unlock()
if c.onEvictedCB != nil && evicted {
c.onEvictedCB(ctx, k, v)
}
return nil, false, evicted
}
// Remove removes the provided key from the cache.
func (c *Cache[K, V]) Remove(ctx context.Context, key K) (present bool) {
var k K
var v V
c.lock.Lock()
present = c.lru.Remove(ctx, key)
if c.onEvictedCB != nil && present {
k, v = c.evictedKeys[0], c.evictedVals[0]
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
}
c.lock.Unlock()
if c.onEvictedCB != nil && present {
c.onEvicted(ctx, k, v)
}
return
}
// Resize changes the cache size.
func (c *Cache[K, V]) Resize(ctx context.Context, size int) (evicted int) {
var ks []K
var vs []V
c.lock.Lock()
evicted = c.lru.Resize(ctx, size)
if c.onEvictedCB != nil && evicted > 0 {
ks, vs = c.evictedKeys, c.evictedVals
c.initEvictBuffers()
}
c.lock.Unlock()
if c.onEvictedCB != nil && evicted > 0 {
for i := 0; i < len(ks); i++ {
c.onEvictedCB(ctx, ks[i], vs[i])
}
}
return evicted
}
// RemoveOldest removes the oldest item from the cache.
func (c *Cache[K, V]) RemoveOldest(ctx context.Context) (key *K, value *V, ok bool) {
var k K
var v V
c.lock.Lock()
key, value, ok = c.lru.RemoveOldest(ctx)
if c.onEvictedCB != nil && ok {
k, v = c.evictedKeys[0], c.evictedVals[0]
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
}
c.lock.Unlock()
if c.onEvictedCB != nil && ok {
c.onEvictedCB(ctx, k, v)
}
return
}
// GetOldest returns the oldest entry
func (c *Cache[K, V]) GetOldest() (key *K, value *V, ok bool) {
c.lock.RLock()
key, value, ok = c.lru.GetOldest()
c.lock.RUnlock()
return
}
// Keys returns a slice of the keys in the cache, from oldest to newest.
func (c *Cache[K, V]) Keys() []K {
c.lock.RLock()
keys := c.lru.Keys()
c.lock.RUnlock()
return keys
}
// Len returns the number of items in the cache.
func (c *Cache[K, V]) Len() int {
c.lock.RLock()
length := c.lru.Len()
c.lock.RUnlock()
return length
}

View File

@ -1,131 +0,0 @@
package cache_test
import (
"context"
"testing"
"github.com/matryer/is"
"go.sour.is/ev/pkg/cache"
)
func TestCache(t *testing.T) {
is := is.New(t)
ctx := context.Background()
c, err := cache.NewCache[string, int](1)
is.NoErr(err)
evicted := c.Add(ctx, "one", 1)
is.True(!evicted)
is.True(c.Contains("one"))
_, ok := c.Peek("one")
is.True(ok)
ok, evicted = c.ContainsOrAdd(ctx, "two", 2)
is.True(!ok)
is.True(evicted)
is.True(!c.Contains("one"))
is.True(c.Contains("two"))
is.Equal(c.Len(), 1)
is.Equal(c.Keys(), []string{"two"})
v, ok := c.Get("two")
is.True(ok)
is.Equal(*v, 2)
evictCount := c.Resize(ctx, 100)
is.True(evictCount == 0)
c.Add(ctx, "one", 1)
prev, ok, evicted := c.PeekOrAdd(ctx, "three", 3)
is.True(!ok)
is.True(!evicted)
is.Equal(prev, nil)
key, value, ok := c.GetOldest()
is.True(ok)
is.Equal(*key, "two")
is.Equal(*value, 2)
key, value, ok = c.RemoveOldest(ctx)
is.True(ok)
is.Equal(*key, "two")
is.Equal(*value, 2)
c.Remove(ctx, "one")
c.Purge(ctx)
is.True(!c.Contains("three"))
}
func TestCacheWithEvict(t *testing.T) {
is := is.New(t)
ctx := context.Background()
evictions := 0
c, err := cache.NewWithEvict(1, func(ctx context.Context, s string, i int) { evictions++ })
is.NoErr(err)
key, value, ok := c.GetOldest()
is.True(!ok)
is.Equal(key, nil)
is.Equal(value, nil)
key, value, ok = c.RemoveOldest(ctx)
is.True(!ok)
is.Equal(key, nil)
is.Equal(value, nil)
evicted := c.Add(ctx, "one", 1)
is.True(!evicted)
is.True(c.Contains("one"))
_, ok = c.Peek("one")
is.True(ok)
ok, evicted = c.ContainsOrAdd(ctx, "two", 2)
is.True(!ok)
is.True(evicted)
is.True(!c.Contains("one"))
is.True(c.Contains("two"))
is.Equal(c.Len(), 1)
is.Equal(c.Keys(), []string{"two"})
v, ok := c.Get("two")
is.True(ok)
is.Equal(*v, 2)
evictCount := c.Resize(ctx, 100)
is.True(evictCount == 0)
c.Add(ctx, "one", 1)
prev, ok, evicted := c.PeekOrAdd(ctx, "three", 3)
is.True(!ok)
is.True(!evicted)
is.Equal(prev, nil)
key, value, ok = c.GetOldest()
is.True(ok)
is.Equal(*key, "two")
is.Equal(*value, 2)
key, value, ok = c.RemoveOldest(ctx)
is.True(ok)
is.Equal(*key, "two")
is.Equal(*value, 2)
c.Resize(ctx, 1)
c.Purge(ctx)
is.True(!c.Contains("three"))
is.Equal(evictions, 4)
}

235
pkg/cache/list.go vendored
View File

@ -1,235 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package list implements a doubly linked list.
//
// To iterate over a list (where l is a *List):
//
// for e := l.Front(); e != nil; e = e.Next() {
// // do something with e.Value
// }
package cache
// Element is an element of a linked list.
type Element[V any] struct {
// Next and previous pointers in the doubly-linked list of elements.
// To simplify the implementation, internally a list l is implemented
// as a ring, such that &l.root is both the next element of the last
// list element (l.Back()) and the previous element of the first list
// element (l.Front()).
next, prev *Element[V]
// The list to which this element belongs.
list *List[V]
// The value stored with this element.
Value V
}
// Next returns the next list element or nil.
func (e *Element[V]) Next() *Element[V] {
if p := e.next; e.list != nil && p != &e.list.root {
return p
}
return nil
}
// Prev returns the previous list element or nil.
func (e *Element[V]) Prev() *Element[V] {
if p := e.prev; e.list != nil && p != &e.list.root {
return p
}
return nil
}
// List represents a doubly linked list.
// The zero value for List is an empty list ready to use.
type List[V any] struct {
root Element[V] // sentinel list element, only &root, root.prev, and root.next are used
len int // current list length excluding (this) sentinel element
}
// Init initializes or clears list l.
func (l *List[V]) Init() *List[V] {
l.root.next = &l.root
l.root.prev = &l.root
l.len = 0
return l
}
// NewList returns an initialized list.
func NewList[V any]() *List[V] { return new(List[V]).Init() }
// Len returns the number of elements of list l.
// The complexity is O(1).
func (l *List[V]) Len() int { return l.len }
// Front returns the first element of list l or nil if the list is empty.
func (l *List[V]) Front() *Element[V] {
if l.len == 0 {
return nil
}
return l.root.next
}
// Back returns the last element of list l or nil if the list is empty.
func (l *List[V]) Back() *Element[V] {
if l.len == 0 {
return nil
}
return l.root.prev
}
// lazyInit lazily initializes a zero List value.
func (l *List[V]) lazyInit() {
if l.root.next == nil {
l.Init()
}
}
// insert inserts e after at, increments l.len, and returns e.
func (l *List[V]) insert(e, at *Element[V]) *Element[V] {
e.prev = at
e.next = at.next
e.prev.next = e
e.next.prev = e
e.list = l
l.len++
return e
}
// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
func (l *List[V]) insertValue(v V, at *Element[V]) *Element[V] {
return l.insert(&Element[V]{Value: v}, at)
}
// remove removes e from its list, decrements l.len
func (l *List[V]) remove(e *Element[V]) {
e.prev.next = e.next
e.next.prev = e.prev
e.next = nil // avoid memory leaks
e.prev = nil // avoid memory leaks
e.list = nil
l.len--
}
// move moves e to next to at.
func (l *List[V]) move(e, at *Element[V]) {
if e == at {
return
}
e.prev.next = e.next
e.next.prev = e.prev
e.prev = at
e.next = at.next
e.prev.next = e
e.next.prev = e
}
// Remove removes e from l if e is an element of list l.
// It returns the element value e.Value.
// The element must not be nil.
func (l *List[V]) Remove(e *Element[V]) any {
if e.list == l {
// if e.list == l, l must have been initialized when e was inserted
// in l or l == nil (e is a zero Element) and l.remove will crash
l.remove(e)
}
return e.Value
}
// PushFront inserts a new element e with value v at the front of list l and returns e.
func (l *List[V]) PushFront(v V) *Element[V] {
l.lazyInit()
return l.insertValue(v, &l.root)
}
// PushBack inserts a new element e with value v at the back of list l and returns e.
func (l *List[V]) PushBack(v V) *Element[V] {
l.lazyInit()
return l.insertValue(v, l.root.prev)
}
// InsertBefore inserts a new element e with value v immediately before mark and returns e.
// If mark is not an element of l, the list is not modified.
// The mark must not be nil.
func (l *List[V]) InsertBefore(v V, mark *Element[V]) *Element[V] {
if mark.list != l {
return nil
}
// see comment in List.Remove about initialization of l
return l.insertValue(v, mark.prev)
}
// InsertAfter inserts a new element e with value v immediately after mark and returns e.
// If mark is not an element of l, the list is not modified.
// The mark must not be nil.
func (l *List[V]) InsertAfter(v V, mark *Element[V]) *Element[V] {
if mark.list != l {
return nil
}
// see comment in List.Remove about initialization of l
return l.insertValue(v, mark)
}
// MoveToFront moves element e to the front of list l.
// If e is not an element of l, the list is not modified.
// The element must not be nil.
func (l *List[V]) MoveToFront(e *Element[V]) {
if e.list != l || l.root.next == e {
return
}
// see comment in List.Remove about initialization of l
l.move(e, &l.root)
}
// MoveToBack moves element e to the back of list l.
// If e is not an element of l, the list is not modified.
// The element must not be nil.
func (l *List[V]) MoveToBack(e *Element[V]) {
if e.list != l || l.root.prev == e {
return
}
// see comment in List.Remove about initialization of l
l.move(e, l.root.prev)
}
// MoveBefore moves element e to its new position before mark.
// If e or mark is not an element of l, or e == mark, the list is not modified.
// The element and mark must not be nil.
func (l *List[V]) MoveBefore(e, mark *Element[V]) {
if e.list != l || e == mark || mark.list != l {
return
}
l.move(e, mark.prev)
}
// MoveAfter moves element e to its new position after mark.
// If e or mark is not an element of l, or e == mark, the list is not modified.
// The element and mark must not be nil.
func (l *List[V]) MoveAfter(e, mark *Element[V]) {
if e.list != l || e == mark || mark.list != l {
return
}
l.move(e, mark)
}
// PushBackList inserts a copy of another list at the back of list l.
// The lists l and other may be the same. They must not be nil.
func (l *List[V]) PushBackList(other *List[V]) {
l.lazyInit()
for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
l.insertValue(e.Value, l.root.prev)
}
}
// PushFrontList inserts a copy of another list at the front of list l.
// The lists l and other may be the same. They must not be nil.
func (l *List[V]) PushFrontList(other *List[V]) {
l.lazyInit()
for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
l.insertValue(e.Value, &l.root)
}
}

175
pkg/cache/lru.go vendored
View File

@ -1,175 +0,0 @@
package cache
import (
"context"
"errors"
)
// EvictCallback is used to get a callback when a cache entry is evicted
type EvictCallback[K comparable, V any] func(context.Context, K, V)
// LRU implements a non-thread safe fixed size LRU cache
type LRU[K comparable, V any] struct {
size int
evictList *List[entry[K, V]]
items map[K]*Element[entry[K, V]]
onEvict EvictCallback[K, V]
}
// entry is used to hold a value in the evictList
type entry[K comparable, V any] struct {
key K
value V
}
// NewLRU constructs an LRU of the given size
func NewLRU[K comparable, V any](size int, onEvict EvictCallback[K, V]) (*LRU[K, V], error) {
if size <= 0 {
return nil, errors.New("must provide a positive size")
}
c := &LRU[K, V]{
size: size,
evictList: NewList[entry[K, V]](),
items: make(map[K]*Element[entry[K, V]]),
onEvict: onEvict,
}
return c, nil
}
// Purge is used to completely clear the cache.
func (c *LRU[K, V]) Purge(ctx context.Context) {
for k, v := range c.items {
if c.onEvict != nil {
c.onEvict(ctx, k, v.Value.value)
}
delete(c.items, k)
}
c.evictList.Init()
}
// Add adds a value to the cache. Returns true if an eviction occurred.
func (c *LRU[K, V]) Add(ctx context.Context, key K, value V) (evicted bool) {
// Check for existing item
if ent, ok := c.items[key]; ok {
c.evictList.MoveToFront(ent)
ent.Value.value = value
return false
}
// Add new item
entry := c.evictList.PushFront(entry[K, V]{key, value})
c.items[key] = entry
evict := c.evictList.Len() > c.size
// Verify size not exceeded
if evict {
c.removeOldest(ctx)
}
return evict
}
// Get looks up a key's value from the cache.
func (c *LRU[K, V]) Get(key K) (value *V, ok bool) {
if ent, ok := c.items[key]; ok {
c.evictList.MoveToFront(ent)
if ent == nil {
return nil, false
}
return &ent.Value.value, true
}
return
}
// Contains checks if a key is in the cache, without updating the recent-ness
// or deleting it for being stale.
func (c *LRU[K, V]) Contains(key K) (ok bool) {
_, ok = c.items[key]
return ok
}
// Peek returns the key value (or undefined if not found) without updating
// the "recently used"-ness of the key.
func (c *LRU[K, V]) Peek(key K) (value *V, ok bool) {
if ent, ok := c.items[key]; ok {
return &ent.Value.value, true
}
return nil, false
}
// Remove removes the provided key from the cache, returning if the
// key was contained.
func (c *LRU[K, V]) Remove(ctx context.Context, key K) (present bool) {
if ent, ok := c.items[key]; ok {
c.removeElement(ctx, ent)
return true
}
return false
}
// RemoveOldest removes the oldest item from the cache.
func (c *LRU[K, V]) RemoveOldest(ctx context.Context) (key *K, value *V, ok bool) {
ent := c.evictList.Back()
if ent != nil {
c.removeElement(ctx, ent)
kv := ent.Value
return &kv.key, &kv.value, true
}
return nil, nil, false
}
// GetOldest returns the oldest entry
func (c *LRU[K, V]) GetOldest() (key *K, value *V, ok bool) {
ent := c.evictList.Back()
if ent != nil {
kv := ent.Value
return &kv.key, &kv.value, true
}
return nil, nil, false
}
// Keys returns a slice of the keys in the cache, from oldest to newest.
func (c *LRU[K, V]) Keys() []K {
keys := make([]K, len(c.items))
i := 0
for ent := c.evictList.Back(); ent != nil; ent = ent.Prev() {
keys[i] = ent.Value.key
i++
}
return keys
}
// Len returns the number of items in the cache.
func (c *LRU[K, V]) Len() int {
return c.evictList.Len()
}
// Resize changes the cache size.
func (c *LRU[K, V]) Resize(ctx context.Context, size int) (evicted int) {
diff := c.Len() - size
if diff < 0 {
diff = 0
}
for i := 0; i < diff; i++ {
c.removeOldest(ctx)
}
c.size = size
return diff
}
// removeOldest removes the oldest item from the cache.
func (c *LRU[K, V]) removeOldest(ctx context.Context) {
ent := c.evictList.Back()
if ent != nil {
c.removeElement(ctx, ent)
}
}
// removeElement is used to remove a given list element from the cache
func (c *LRU[K, V]) removeElement(ctx context.Context, e *Element[entry[K, V]]) {
c.evictList.Remove(e)
kv := e.Value
delete(c.items, kv.key)
if c.onEvict != nil {
c.onEvict(ctx, kv.key, kv.value)
}
}

View File

@ -1,160 +0,0 @@
package cron
import (
"context"
"fmt"
"math/rand"
"strconv"
"strings"
"time"
"go.opentelemetry.io/otel/attribute"
"go.sour.is/ev/internal/lg"
"go.sour.is/ev/pkg/locker"
"go.sour.is/ev/pkg/set"
"golang.org/x/sync/errgroup"
)
type task func(context.Context, time.Time) error
type job struct {
Month, Weekday, Day,
Hour, Minute, Second *set.BoundSet[int8]
Task task
}
var DefaultGranularity = time.Minute
type state struct {
queue []task
}
type cron struct {
jobs []job
state *locker.Locked[state]
granularity time.Duration
}
func New(granularity time.Duration) *cron {
return &cron{granularity: granularity, state: locker.New(&state{})}
}
func parseInto(c string, s *set.BoundSet[int8]) *set.BoundSet[int8] {
if c == "*" || c == "" {
s.AddRange(0, 100)
}
for _, split := range strings.Split(c, ",") {
minmax := strings.SplitN(split, "-", 2)
switch len(minmax) {
case 2:
min, _ := strconv.ParseInt(minmax[0], 10, 8)
max, _ := strconv.ParseInt(minmax[1], 10, 8)
s.AddRange(int8(min), int8(max))
default:
min, _ := strconv.ParseInt(minmax[0], 10, 8)
s.Add(int8(min))
}
}
return s
}
// This function creates a new job that occurs at the given day and the given
// 24hour time. Any of the values may be -1 as an "any" match, so passing in
// a day of -1, the event occurs every day; passing in a second value of -1, the
// event will fire every second that the other parameters match.
func (c *cron) NewCron(expr string, task func(context.Context, time.Time) error) {
sp := append(strings.Fields(expr), make([]string, 5)...)[:5]
job := job{
Month: parseInto(sp[4], set.NewBoundSet[int8](1, 12)),
Weekday: parseInto(sp[3], set.NewBoundSet[int8](0, 6)),
Day: parseInto(sp[2], set.NewBoundSet[int8](1, 31)),
Hour: parseInto(sp[1], set.NewBoundSet[int8](0, 23)),
Minute: parseInto(sp[0], set.NewBoundSet[int8](0, 59)),
Task: task,
}
c.jobs = append(c.jobs, job)
}
func (c *cron) RunOnce(ctx context.Context, once func(context.Context, time.Time) error) {
c.state.Use(ctx, func(ctx context.Context, state *state) error {
state.queue = append(state.queue, once)
return nil
})
}
func (cj job) Matches(t time.Time) (ok bool) {
return cj.Month.Has(int8(t.Month())) &&
cj.Day.Has(int8(t.Day())) &&
cj.Weekday.Has(int8(t.Weekday()%7)) &&
cj.Hour.Has(int8(t.Hour())) &&
cj.Minute.Has(int8(t.Minute()))
}
func (cj job) String() string {
return fmt.Sprintf("job[\n m:%s\n h:%s\n d:%s\n w:%s\n M:%s\n]", cj.Minute, cj.Hour, cj.Day, cj.Weekday, cj.Month)
}
func (c *cron) Run(ctx context.Context) error {
tick := time.NewTicker(c.granularity)
defer tick.Stop()
go c.run(ctx, time.Now())
for {
select {
case <-ctx.Done():
return nil
case now := <-tick.C:
// fmt.Println(now.Second(), now.Hour(), now.Day(), int8(now.Weekday()), uint8(now.Month()))
go c.run(ctx, now)
}
}
}
func (c *cron) run(ctx context.Context, now time.Time) {
var run []task
ctx, span := lg.Span(ctx)
defer span.End()
// Add Jitter
timer := time.NewTimer(time.Duration(rand.Intn(300)) * time.Millisecond)
select {
case <-ctx.Done():
timer.Stop()
return
case <-timer.C:
}
span.AddEvent("Cron Run: " + now.Format(time.RFC822))
// fmt.Println("Cron Run: ", now.Format(time.RFC822))
c.state.Use(ctx, func(ctx context.Context, state *state) error {
run = append(run, state.queue...)
state.queue = state.queue[:0]
return nil
})
for _, j := range c.jobs {
if j.Matches(now) {
span.AddEvent(j.String())
run = append(run, j.Task)
}
}
if len(run) == 0 {
return
}
wg, _ := errgroup.WithContext(ctx)
for i := range run {
fn := run[i]
wg.Go(func() error { return fn(ctx, now) })
}
span.SetAttributes(
attribute.String("tick", now.String()),
attribute.Int("count", len(run)),
)
err := wg.Wait()
span.RecordError(err)
}

View File

@ -13,16 +13,17 @@ import (
"github.com/tidwall/wal" "github.com/tidwall/wal"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric/instrument/syncint64" "go.opentelemetry.io/otel/metric"
"go.uber.org/multierr" "go.uber.org/multierr"
"go.sour.is/pkg/cache"
"go.sour.is/pkg/lg"
"go.sour.is/pkg/locker"
"go.sour.is/pkg/math"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/driver"
"go.sour.is/ev/pkg/cache" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/driver"
"go.sour.is/ev/pkg/es/event"
"go.sour.is/ev/pkg/locker"
"go.sour.is/ev/pkg/math"
) )
const CachSize = 1000 const CachSize = 1000
@ -35,10 +36,10 @@ type diskStore struct {
path string path string
openlogs *locker.Locked[openlogs] openlogs *locker.Locked[openlogs]
m_disk_open syncint64.Counter m_disk_open metric.Int64Counter
m_disk_evict syncint64.Counter m_disk_evict metric.Int64Counter
m_disk_read syncint64.Counter m_disk_read metric.Int64Counter
m_disk_write syncint64.Counter m_disk_write metric.Int64Counter
} }
const AppendOnly = ev.AppendOnly const AppendOnly = ev.AppendOnly
@ -53,16 +54,16 @@ func Init(ctx context.Context) error {
m := lg.Meter(ctx) m := lg.Meter(ctx)
var err, errs error var err, errs error
d.m_disk_open, err = m.SyncInt64().Counter("disk_open") d.m_disk_open, err = m.Int64Counter("disk_open")
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
d.m_disk_evict, err = m.SyncInt64().Counter("disk_evict") d.m_disk_evict, err = m.Int64Counter("disk_evict")
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
d.m_disk_read, err = m.SyncInt64().Counter("disk_read") d.m_disk_read, err = m.Int64Counter("disk_read")
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
d.m_disk_write, err = m.SyncInt64().Counter("disk_write") d.m_disk_write, err = m.Int64Counter("disk_write")
errs = multierr.Append(errs, err) errs = multierr.Append(errs, err)
ev.Register(ctx, "file", d) ev.Register(ctx, "file", d)

View File

@ -4,7 +4,7 @@ package driver
import ( import (
"context" "context"
"go.sour.is/ev/pkg/es/event" "go.sour.is/ev/pkg/event"
) )
type Driver interface { type Driver interface {

View File

@ -5,12 +5,13 @@ import (
"context" "context"
"fmt" "fmt"
"go.sour.is/pkg/lg"
"go.sour.is/pkg/locker"
"go.sour.is/pkg/math"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/driver"
"go.sour.is/ev/pkg/es/driver" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event"
"go.sour.is/ev/pkg/locker"
"go.sour.is/ev/pkg/math"
) )
type state struct { type state struct {

View File

@ -5,10 +5,11 @@ import (
"context" "context"
"strings" "strings"
"go.sour.is/pkg/lg"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/driver"
"go.sour.is/ev/pkg/es/driver" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event"
) )
type projector struct { type projector struct {

View File

@ -5,10 +5,11 @@ import (
"testing" "testing"
"github.com/matryer/is" "github.com/matryer/is"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/pkg/es/driver" "go.sour.is/ev/pkg/driver"
"go.sour.is/ev/pkg/es/driver/projecter" "go.sour.is/ev/pkg/driver/projecter"
"go.sour.is/ev/pkg/es/event" "go.sour.is/ev/pkg/event"
) )
type mockDriver struct { type mockDriver struct {

View File

@ -5,9 +5,9 @@ import (
"errors" "errors"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/driver"
"go.sour.is/ev/pkg/es/driver" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event" "go.sour.is/pkg/lg"
) )
type resolvelinks struct { type resolvelinks struct {

View File

@ -10,10 +10,10 @@ import (
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/driver"
"go.sour.is/ev/pkg/es/driver" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/locker" "go.sour.is/pkg/locker"
) )
type state struct { type state struct {

40
pkg/env/env.go vendored
View File

@ -1,40 +0,0 @@
package env
import (
"log"
"os"
"strings"
)
func Default(name, defaultValue string) string {
name = strings.TrimSpace(name)
defaultValue = strings.TrimSpace(defaultValue)
if v := strings.TrimSpace(os.Getenv(name)); v != "" {
log.Println("# ", name, "=", v)
return v
}
log.Println("# ", name, "=", defaultValue, "(default)")
return defaultValue
}
type secret string
func (s secret) String() string {
if s == "" {
return "(nil)"
}
return "***"
}
func (s secret) Secret() string {
return string(s)
}
func Secret(name, defaultValue string) secret {
name = strings.TrimSpace(name)
defaultValue = strings.TrimSpace(defaultValue)
if v := strings.TrimSpace(os.Getenv(name)); v != "" {
log.Println("# ", name, "=", secret(v))
return secret(v)
}
log.Println("# ", name, "=", secret(defaultValue), "(default)")
return secret(defaultValue)
}

View File

@ -1,5 +1,5 @@
type Meta @goModel(model: "go.sour.is/ev/pkg/es/event.Meta") { type Meta @goModel(model: "go.sour.is/ev/pkg/event.Meta") {
eventID: String! @goField(name: "getEventID") eventID: String! @goField(name: "getEventID")
streamID: String! @goField(name: "ActualStreamID") streamID: String! @goField(name: "ActualStreamID")
position: Int! @goField(name: "ActualPosition") position: Int! @goField(name: "ActualPosition")

View File

@ -9,10 +9,11 @@ import (
"net/http" "net/http"
"time" "time"
"go.sour.is/pkg/gql"
"go.sour.is/pkg/lg"
"go.sour.is/ev" "go.sour.is/ev"
"go.sour.is/ev/internal/lg" "go.sour.is/ev/pkg/event"
"go.sour.is/ev/pkg/es/event"
"go.sour.is/ev/pkg/gql"
) )
type EventResolver interface { type EventResolver interface {

View File

@ -3,7 +3,7 @@ package event_test
import ( import (
"testing" "testing"
"go.sour.is/ev/pkg/es/event" "go.sour.is/ev/pkg/event"
) )
type Agg struct { type Agg struct {

View File

@ -8,7 +8,7 @@ import (
"github.com/matryer/is" "github.com/matryer/is"
"go.sour.is/ev/pkg/es/event" "go.sour.is/ev/pkg/event"
) )
type DummyEvent struct { type DummyEvent struct {

View File

@ -10,8 +10,8 @@ import (
"reflect" "reflect"
"strings" "strings"
"go.sour.is/ev/internal/lg" "go.sour.is/pkg/lg"
"go.sour.is/ev/pkg/locker" "go.sour.is/pkg/locker"
) )
type config struct { type config struct {

View File

@ -1,67 +0,0 @@
package gql
import (
"context"
"encoding/json"
"go.sour.is/ev/pkg/es/event"
)
type Edge interface {
IsEdge()
}
type Connection struct {
Paging *PageInfo `json:"paging"`
Edges []Edge `json:"edges"`
}
type PostEvent struct {
ID string `json:"id"`
Payload string `json:"payload"`
Tags []string `json:"tags"`
Meta *event.Meta `json:"meta"`
}
func (PostEvent) IsEdge() {}
func (e *PostEvent) PayloadJSON(ctx context.Context) (m map[string]interface{}, err error) {
err = json.Unmarshal([]byte(e.Payload), &m)
return
}
type PageInfo struct {
Next bool `json:"next"`
Prev bool `json:"prev"`
Begin uint64 `json:"begin"`
End uint64 `json:"end"`
}
type PageInput struct {
After *int64 `json:"after"`
Before *int64 `json:"before"`
Count *int64 `json:"count"`
}
func (p *PageInput) GetIdx(v int64) int64 {
if p == nil {
// pass
} else if p.Before != nil {
return (*p.Before)
} else if p.After != nil {
return *p.After
}
return v
}
func (p *PageInput) GetCount(v int64) int64 {
if p == nil || p.Count == nil {
return v
} else if p.Before != nil {
return -(*p.Count)
} else if p.After != nil {
return *p.Count
}
return *p.Count
}

View File

@ -1,14 +0,0 @@
package gql
import "context"
func ToContext[K comparable, V any](ctx context.Context, key K, value V) context.Context {
return context.WithValue(ctx, key, value)
}
func FromContext[K comparable, V any](ctx context.Context, key K) V {
var empty V
if v, ok := ctx.Value(key).(V); ok {
return v
}
return empty
}

View File

@ -1,120 +0,0 @@
package graphiql
import (
"html/template"
"net/http"
"net/url"
)
var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{.title}}</title>
<style>
body {
height: 100%;
margin: 0;
width: 100%;
overflow: hidden;
}
#graphiql {
height: 100vh;
}
</style>
<script
src="https://cdn.jsdelivr.net/npm/react@{{.reactVersion}}/umd/react.production.min.js"
integrity="{{.reactSRI}}"
crossorigin="anonymous"
></script>
<script
src="https://cdn.jsdelivr.net/npm/react-dom@{{.reactVersion}}/umd/react-dom.production.min.js"
integrity="{{.reactDOMSRI}}"
crossorigin="anonymous"
></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/graphiql@{{.version}}/graphiql.min.css"
x-integrity="{{.cssSRI}}"
crossorigin="anonymous"
/>
</head>
<body>
<div id="graphiql">Loading...</div>
<script
src="https://cdn.jsdelivr.net/npm/graphiql@{{.version}}/graphiql.min.js"
x-integrity="{{.jsSRI}}"
crossorigin="anonymous"
></script>
<script>
{{- if .endpointIsAbsolute}}
const url = {{.endpoint}};
const subscriptionUrl = {{.subscriptionEndpoint}};
{{- else}}
const url = location.protocol + '//' + location.host + {{.endpoint}};
const wsProto = location.protocol == 'https:' ? 'wss:' : 'ws:';
const subscriptionUrl = wsProto + '//' + location.host + {{.endpoint}};
{{- end}}
const fetcher = GraphiQL.createFetcher({ url, subscriptionUrl });
ReactDOM.render(
React.createElement(GraphiQL, {
fetcher: fetcher,
isHeadersEditorEnabled: true,
shouldPersistHeaders: true
}),
document.getElementById('graphiql'),
);
</script>
</body>
</html>
`))
// Handler responsible for setting up the playground
func Handler(title string, endpoint string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "text/html; charset=UTF-8")
err := page.Execute(w, map[string]interface{}{
"title": title,
"endpoint": endpoint,
"endpointIsAbsolute": endpointHasScheme(endpoint),
"subscriptionEndpoint": getSubscriptionEndpoint(endpoint),
"version": "2.4.1",
"reactVersion": "17.0.2",
"cssSRI": "sha256-bGeEsMhcAqeXBjh2w0eQzBTFAxwlxhM0PKIKqMshlnk=",
"jsSRI": "sha256-s+f7CFAPSUIygFnRC2nfoiEKd3liCUy+snSdYFAoLUc=",
"reactSRI": "sha256-Ipu/TQ50iCCVZBUsZyNJfxrDk0E2yhaEIz0vqI+kFG8=",
"reactDOMSRI": "sha256-nbMykgB6tsOFJ7OdVmPpdqMFVk4ZsqWocT6issAPUF0=",
})
if err != nil {
panic(err)
}
}
}
// endpointHasScheme checks if the endpoint has a scheme.
func endpointHasScheme(endpoint string) bool {
u, err := url.Parse(endpoint)
return err == nil && u.Scheme != ""
}
// getSubscriptionEndpoint returns the subscription endpoint for the given
// endpoint if it is parsable as a URL, or an empty string.
func getSubscriptionEndpoint(endpoint string) string {
u, err := url.Parse(endpoint)
if err != nil {
return ""
}
switch u.Scheme {
case "https":
u.Scheme = "wss"
default:
u.Scheme = "ws"
}
return u.String()
}

View File

@ -1,62 +0,0 @@
package playground
import (
"html/template"
"net/http"
)
var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8/>
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<link rel="shortcut icon" href="https://graphcool-playground.netlify.com/favicon.png">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/css/index.css"
integrity="{{ .cssSRI }}" crossorigin="anonymous"/>
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/favicon.png"
integrity="{{ .faviconSRI }}" crossorigin="anonymous"/>
<script src="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/js/middleware.js"
integrity="{{ .jsSRI }}" crossorigin="anonymous"></script>
<title>{{.title}}</title>
</head>
<body>
<style type="text/css">
html { font-family: "Open Sans", sans-serif; overflow: hidden; }
body { margin: 0; background: #172a3a; }
</style>
<div id="root"/>
<script type="text/javascript">
window.addEventListener('load', function (event) {
const root = document.getElementById('root');
root.classList.add('playgroundIn');
const wsProto = location.protocol == 'https:' ? 'wss:' : 'ws:'
GraphQLPlayground.init(root, {
endpoint: location.protocol + '//' + location.host + '{{.endpoint}}',
subscriptionsEndpoint: wsProto + '//' + location.host + '{{.endpoint }}',
shareEnabled: true,
settings: {
'request.credentials': 'same-origin'
}
})
})
</script>
</body>
</html>
`))
func Handler(title string, endpoint string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "text/html")
err := page.Execute(w, map[string]string{
"title": title,
"endpoint": endpoint,
"version": "1.7.28",
"cssSRI": "sha256-dKnNLEFwKSVFpkpjRWe+o/jQDM6n/JsvQ0J3l5Dk3fc=",
"faviconSRI": "sha256-GhTyE+McTU79R4+pRO6ih+4TfsTOrpPwD8ReKFzb3PM=",
"jsSRI": "sha256-VVwEZwxs4qS5W7E+/9nXINYgr/BJRWKOi/rTMUdmmWg=",
})
if err != nil {
panic(err)
}
}
}

View File

@ -1,143 +0,0 @@
package resolver
import (
"context"
"fmt"
"net/http"
"os"
"reflect"
"runtime/debug"
"time"
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/handler/extension"
"github.com/99designs/gqlgen/graphql/handler/lru"
"github.com/99designs/gqlgen/graphql/handler/transport"
"github.com/vektah/gqlparser/v2/gqlerror"
"github.com/gorilla/websocket"
"github.com/ravilushqa/otelgqlgen"
"go.sour.is/ev/internal/lg"
"go.sour.is/ev/pkg/gql/graphiql"
"go.sour.is/ev/pkg/gql/playground"
)
type BaseResolver interface {
ExecutableSchema() graphql.ExecutableSchema
BaseResolver() IsResolver
}
type Resolver[T BaseResolver] struct {
res T
CheckOrigin func(r *http.Request) bool
}
type IsResolver interface {
IsResolver()
}
var defaultCheckOrign = func(r *http.Request) bool {
return true
}
func New[T BaseResolver](ctx context.Context, base T, resolvers ...IsResolver) (*Resolver[T], error) {
_, span := lg.Span(ctx)
defer span.End()
noop := reflect.ValueOf(base.BaseResolver())
v := reflect.ValueOf(base)
v = reflect.Indirect(v)
outer:
for _, idx := range reflect.VisibleFields(v.Type()) {
field := v.FieldByIndex(idx.Index)
for i := range resolvers {
rs := reflect.ValueOf(resolvers[i])
if field.IsNil() && rs.Type().Implements(field.Type()) {
// log.Print("found ", field.Type().Name())
span.AddEvent(fmt.Sprint("found ", field.Type().Name()))
field.Set(rs)
continue outer
}
}
// log.Print(fmt.Sprint("default ", field.Type().Name()))
span.AddEvent(fmt.Sprint("default ", field.Type().Name()))
field.Set(noop)
}
return &Resolver[T]{res: base, CheckOrigin: defaultCheckOrign}, nil
}
func (r *Resolver[T]) Resolver() T {
return r.res
}
// ChainMiddlewares will check all embeded resolvers for a GetMiddleware func and add to handler.
func (r *Resolver[T]) ChainMiddlewares(h http.Handler) http.Handler {
v := reflect.ValueOf(r.Resolver()) // Get reflected value of *Resolver
v = reflect.Indirect(v) // Get the pointed value (returns a zero value on nil)
for _, idx := range reflect.VisibleFields(v.Type()) {
field := v.FieldByIndex(idx.Index)
// log.Print("middleware ", field.Type().Name())
if !field.CanInterface() { // Skip non-interface types.
continue
}
if iface, ok := field.Interface().(interface {
GetMiddleware() func(http.Handler) http.Handler
}); ok {
h = iface.GetMiddleware()(h) // Append only items that fulfill the interface.
}
}
return h
}
func (r *Resolver[T]) RegisterHTTP(mux *http.ServeMux) {
gql := NewServer(r.Resolver().ExecutableSchema(), r.CheckOrigin)
gql.SetRecoverFunc(NoopRecover)
gql.Use(otelgqlgen.Middleware())
mux.Handle("/gql", lg.Htrace(r.ChainMiddlewares(gql), "gql"))
mux.Handle("/graphiql", graphiql.Handler("GraphiQL playground", "/gql"))
mux.Handle("/playground", playground.Handler("GraphQL playground", "/gql"))
}
func NoopRecover(ctx context.Context, err interface{}) error {
if err, ok := err.(string); ok && err == "not implemented" {
return gqlerror.Errorf("not implemented")
}
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr)
debug.PrintStack()
return gqlerror.Errorf("internal system error")
}
func NewServer(es graphql.ExecutableSchema, checkOrigin func(*http.Request) bool) *handler.Server {
srv := handler.New(es)
srv.AddTransport(transport.Websocket{
Upgrader: websocket.Upgrader{
CheckOrigin: checkOrigin,
},
KeepAlivePingInterval: 10 * time.Second,
})
srv.AddTransport(transport.Options{})
srv.AddTransport(transport.GET{})
srv.AddTransport(transport.POST{})
srv.AddTransport(transport.MultipartForm{})
srv.SetQueryCache(lru.New(1000))
srv.Use(extension.Introspection{})
srv.Use(extension.AutomaticPersistedQuery{
Cache: lru.New(100),
})
return srv
}

View File

@ -1,74 +0,0 @@
package locker
import (
"context"
"errors"
"fmt"
"go.opentelemetry.io/otel/attribute"
"go.sour.is/ev/internal/lg"
)
type Locked[T any] struct {
state chan *T
}
// New creates a new locker for the given value.
func New[T any](initial *T) *Locked[T] {
s := &Locked[T]{}
s.state = make(chan *T, 1)
s.state <- initial
return s
}
type ctxKey struct{ name string }
// Use will call the function with the locked value
func (s *Locked[T]) Use(ctx context.Context, fn func(context.Context, *T) error) error {
if s == nil {
return fmt.Errorf("locker not initialized")
}
key := ctxKey{fmt.Sprintf("%p", s)}
if value := ctx.Value(key); value != nil {
return fmt.Errorf("%w: %T", ErrNested, s)
}
ctx = context.WithValue(ctx, key, key)
ctx, span := lg.Span(ctx)
defer span.End()
var t T
span.SetAttributes(
attribute.String("typeOf", fmt.Sprintf("%T", t)),
)
if ctx.Err() != nil {
return ctx.Err()
}
select {
case state := <-s.state:
defer func() { s.state <- state }()
return fn(ctx, state)
case <-ctx.Done():
return ctx.Err()
}
}
// Copy will return a shallow copy of the locked object.
func (s *Locked[T]) Copy(ctx context.Context) (T, error) {
var t T
err := s.Use(ctx, func(ctx context.Context, c *T) error {
if c != nil {
t = *c
}
return nil
})
return t, err
}
var ErrNested = errors.New("nested locker call")

View File

@ -1,96 +0,0 @@
package locker_test
import (
"context"
"errors"
"testing"
"github.com/matryer/is"
"go.sour.is/ev/pkg/locker"
)
type config struct {
Value string
Counter int
}
func TestLocker(t *testing.T) {
is := is.New(t)
value := locker.New(&config{})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
err := value.Use(ctx, func(ctx context.Context, c *config) error {
c.Value = "one"
c.Counter++
return nil
})
is.NoErr(err)
c, err := value.Copy(context.Background())
is.NoErr(err)
is.Equal(c.Value, "one")
is.Equal(c.Counter, 1)
wait := make(chan struct{})
go value.Use(ctx, func(ctx context.Context, c *config) error {
c.Value = "two"
c.Counter++
close(wait)
return nil
})
<-wait
cancel()
err = value.Use(ctx, func(ctx context.Context, c *config) error {
c.Value = "three"
c.Counter++
return nil
})
is.True(err != nil)
c, err = value.Copy(context.Background())
is.NoErr(err)
is.Equal(c.Value, "two")
is.Equal(c.Counter, 2)
}
func TestNestedLocker(t *testing.T) {
is := is.New(t)
value := locker.New(&config{})
other := locker.New(&config{})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
err := value.Use(ctx, func(ctx context.Context, c *config) error {
return value.Use(ctx, func(ctx context.Context, t *config) error {
return nil
})
})
is.True(errors.Is(err, locker.ErrNested))
err = value.Use(ctx, func(ctx context.Context, c *config) error {
return other.Use(ctx, func(ctx context.Context, t *config) error {
return nil
})
})
is.NoErr(err)
err = value.Use(ctx, func(ctx context.Context, c *config) error {
return other.Use(ctx, func(ctx context.Context, t *config) error {
return value.Use(ctx, func(ctx context.Context, x *config) error {
return nil
})
})
})
is.True(errors.Is(err, locker.ErrNested))
}

View File

@ -1,71 +0,0 @@
package math
type signed interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}
type unsigned interface {
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}
type integer interface {
signed | unsigned
}
type float interface {
~float32 | ~float64
}
type ordered interface {
integer | float | ~string
}
func Abs[T signed](i T) T {
if i > 0 {
return i
}
return -i
}
func Max[T ordered](i T, candidates ...T) T {
for _, j := range candidates {
if i < j {
i = j
}
}
return i
}
func Min[T ordered](i T, candidates ...T) T {
for _, j := range candidates {
if i > j {
i = j
}
}
return i
}
func PagerBox(first, last uint64, pos, count int64) (uint64, int64) {
var start uint64
if pos >= 0 {
if int64(first) > pos {
start = first
} else {
start = uint64(pos) + 1
}
} else {
start = uint64(int64(last) + pos + 1)
}
switch {
case count > 0:
count = Min(count, int64(last-start)+1)
case pos >= 0 && count < 0:
count = Max(count, int64(first-start))
case pos < 0 && count < 0:
count = Max(count, int64(first-start)-1)
}
if count == 0 || (start < first && count <= 0) || (start > last && count >= 0) {
return 0, 0
}
return start, count
}

View File

@ -1,94 +0,0 @@
package math_test
import (
"testing"
"github.com/matryer/is"
"go.sour.is/ev"
"go.sour.is/ev/pkg/math"
)
func TestMath(t *testing.T) {
is := is.New(t)
is.Equal(5, math.Abs(-5))
is.Equal(math.Abs(5), math.Abs(-5))
is.Equal(10, math.Max(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
is.Equal(1, math.Min(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
is.Equal(1, math.Min(89, 71, 54, 48, 49, 1, 72, 88, 25, 69))
is.Equal(89, math.Max(89, 71, 54, 48, 49, 1, 72, 88, 25, 69))
is.Equal(0.9348207729, math.Max(
0.3943310720,
0.1090868377,
0.9348207729,
0.3525527584,
0.4359833682,
0.7958538081,
0.1439352569,
0.1547311967,
0.6403818871,
0.8618832818,
))
is.Equal(0.1090868377, math.Min(
0.3943310720,
0.1090868377,
0.9348207729,
0.3525527584,
0.4359833682,
0.7958538081,
0.1439352569,
0.1547311967,
0.6403818871,
0.8618832818,
))
}
func TestPagerBox(t *testing.T) {
is := is.New(t)
tests := []struct {
first uint64
last uint64
pos int64
n int64
start uint64
count int64
}{
{1, 10, 0, 10, 1, 10},
{1, 10, 0, 11, 1, 10},
{1, 5, 0, 10, 1, 5},
{1, 10, 4, 10, 5, 6},
{1, 10, 5, 10, 6, 5},
{1, 10, 0, -10, 0, 0},
{1, 10, 1, -1, 2, -1},
{1, 10, 1, -10, 2, -1},
{1, 10, -1, 1, 10, 1},
{1, 10, -2, 10, 9, 2},
{1, 10, -1, -1, 10, -1},
{1, 10, -2, -10, 9, -9},
{1, 10, 0, -10, 0, 0},
{1, 10, 10, 10, 0, 0},
{1, 10, 0, ev.AllEvents, 1, 10},
{1, 10, -1, -ev.AllEvents, 10, -10},
{5, 10, 0, 1, 5, 1},
}
for _, tt := range tests {
start, count := math.PagerBox(tt.first, tt.last, tt.pos, tt.n)
if count > 0 {
t.Log(tt, "|", start, count, int64(start)+count-1)
} else {
t.Log(tt, "|", start, count, int64(start)+count+1)
}
is.Equal(start, tt.start)
is.Equal(count, tt.count)
}
}

View File

@ -1,43 +0,0 @@
package mux
import (
"net/http"
)
type mux struct {
*http.ServeMux
api *http.ServeMux
wellknown *http.ServeMux
}
func (mux *mux) Add(fns ...interface{ RegisterHTTP(*http.ServeMux) }) {
for _, fn := range fns {
// log.Printf("HTTP: %T", fn)
fn.RegisterHTTP(mux.ServeMux)
if fn, ok := fn.(interface{ RegisterAPIv1(*http.ServeMux) }); ok {
// log.Printf("APIv1: %T", fn)
fn.RegisterAPIv1(mux.api)
}
if fn, ok := fn.(interface{ RegisterWellKnown(*http.ServeMux) }); ok {
// log.Printf("WellKnown: %T", fn)
fn.RegisterWellKnown(mux.wellknown)
}
}
}
func New() *mux {
mux := &mux{
api: http.NewServeMux(),
wellknown: http.NewServeMux(),
ServeMux: http.NewServeMux(),
}
mux.Handle("/api/v1/", http.StripPrefix("/api/v1", mux.api))
mux.Handle("/.well-known/", http.StripPrefix("/.well-known", mux.wellknown))
return mux
}
type RegisterHTTP func(*http.ServeMux)
func (fn RegisterHTTP) RegisterHTTP(mux *http.ServeMux) { fn(mux) }

View File

@ -1,104 +0,0 @@
package mux_test
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/matryer/is"
"go.sour.is/ev/pkg/mux"
)
type mockHTTP struct {
onServeHTTP func()
onServeAPIv1 func()
onServeWellKnown func()
}
func (*mockHTTP) ServeFn(fn func()) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { fn() }
}
func (h *mockHTTP) RegisterHTTP(mux *http.ServeMux) {
mux.HandleFunc("/", h.ServeFn(h.onServeHTTP))
}
func (h *mockHTTP) RegisterAPIv1(mux *http.ServeMux) {
mux.HandleFunc("/ping", h.ServeFn(h.onServeAPIv1))
}
func (h *mockHTTP) RegisterWellKnown(mux *http.ServeMux) {
mux.HandleFunc("/echo", h.ServeFn(h.onServeWellKnown))
}
func TestHttp(t *testing.T) {
is := is.New(t)
called := false
calledAPIv1 := false
calledWellKnown := false
mux := mux.New()
mux.Add(&mockHTTP{
func() { called = true },
func() { calledAPIv1 = true },
func() { calledWellKnown = true },
})
is.True(mux != nil)
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/", nil)
mux.ServeHTTP(w, r)
is.True(called)
is.True(!calledAPIv1)
is.True(!calledWellKnown)
}
func TestHttpAPIv1(t *testing.T) {
is := is.New(t)
called := false
calledAPIv1 := false
calledWellKnown := false
mux := mux.New()
mux.Add(&mockHTTP{
func() { called = true },
func() { calledAPIv1 = true },
func() { calledWellKnown = true },
})
is.True(mux != nil)
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/api/v1/ping", nil)
mux.ServeHTTP(w, r)
is.True(!called)
is.True(calledAPIv1)
is.True(!calledWellKnown)
}
func TestHttpWellKnown(t *testing.T) {
is := is.New(t)
called := false
calledAPIv1 := false
calledWellKnown := false
mux := mux.New()
mux.Add(&mockHTTP{
func() { called = true },
func() { calledAPIv1 = true },
func() { calledWellKnown = true },
})
is.True(mux != nil)
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/.well-known/echo", nil)
mux.ServeHTTP(w, r)
is.True(!called)
is.True(!calledAPIv1)
is.True(calledWellKnown)
}

View File

@ -1,178 +0,0 @@
package service
import (
"context"
"log"
"net/http"
"runtime/debug"
"sort"
"strings"
"time"
"go.opentelemetry.io/otel/attribute"
"go.sour.is/ev/internal/lg"
"go.sour.is/ev/pkg/cron"
"go.uber.org/multierr"
"golang.org/x/sync/errgroup"
)
type crontab interface {
NewCron(expr string, task func(context.Context, time.Time) error)
RunOnce(ctx context.Context, once func(context.Context, time.Time) error)
}
type Harness struct {
crontab
Services []any
onStart []func(context.Context) error
onRunning chan struct{}
onStop []func(context.Context) error
}
func (s *Harness) Setup(ctx context.Context, apps ...application) error {
ctx, span := lg.Span(ctx)
defer span.End()
// setup crontab
c := cron.New(cron.DefaultGranularity)
s.OnStart(c.Run)
s.onRunning = make(chan struct{})
s.crontab = c
var err error
for _, app := range apps {
err = multierr.Append(err, app(ctx, s))
}
span.RecordError(err)
return err
}
func (s *Harness) OnStart(fn func(context.Context) error) {
s.onStart = append(s.onStart, fn)
}
func (s *Harness) OnRunning() <-chan struct{} {
return s.onRunning
}
func (s *Harness) OnStop(fn func(context.Context) error) {
s.onStop = append(s.onStop, fn)
}
func (s *Harness) Add(svcs ...any) {
s.Services = append(s.Services, svcs...)
}
func (s *Harness) stop(ctx context.Context) error {
g, _ := errgroup.WithContext(ctx)
for i := range s.onStop {
fn := s.onStop[i]
g.Go(func() error {
if err := fn(ctx); err != nil && err != http.ErrServerClosed {
return err
}
return nil
})
}
return g.Wait()
}
func (s *Harness) Run(ctx context.Context, appName, version string) error {
{
ctx, span := lg.Span(ctx)
log.Println(appName, version)
span.SetAttributes(
attribute.String("app", appName),
attribute.String("version", version),
)
Mup, err := lg.Meter(ctx).SyncInt64().UpDownCounter("up")
if err != nil {
return err
}
Mup.Add(ctx, 1)
span.End()
}
g, _ := errgroup.WithContext(ctx)
g.Go(func() error {
<-ctx.Done()
// shutdown jobs
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
return s.stop(ctx)
})
for i := range s.onStart {
fn := s.onStart[i]
g.Go(func() error { return fn(ctx) })
}
close(s.onRunning)
err := g.Wait()
return err
}
type application func(context.Context, *Harness) error // Len is the number of elements in the collection.
type appscore struct {
score int
application
}
type Apps []appscore
func (a *Apps) Apps() []application {
sort.Sort(a)
lis := make([]application, len(*a))
for i, app := range *a {
lis[i] = app.application
}
return lis
}
// Len is the number of elements in the collection.
func (a *Apps) Len() int {
if a == nil {
return 0
}
return len(*a)
}
// Less reports whether the element with index i
func (a *Apps) Less(i int, j int) bool {
if a == nil {
return false
}
return (*a)[i].score < (*a)[j].score
}
// Swap swaps the elements with indexes i and j.
func (a *Apps) Swap(i int, j int) {
if a == nil {
return
}
(*a)[i], (*a)[j] = (*a)[j], (*a)[i]
}
func (a *Apps) Register(score int, app application) (none struct{}) {
if a == nil {
return
}
*a = append(*a, appscore{score, app})
return
}
func AppName() (string, string) {
if info, ok := debug.ReadBuildInfo(); ok {
_, name, _ := strings.Cut(info.Main.Path, "/")
name = strings.Replace(name, "-", ".", -1)
name = strings.Replace(name, "/", "-", -1)
return name, info.Main.Version
}
return "sour.is-app", "(devel)"
}

View File

@ -1,137 +0,0 @@
package set
import (
"fmt"
"sort"
"strings"
"go.sour.is/ev/pkg/math"
)
type Set[T comparable] map[T]struct{}
func New[T comparable](items ...T) Set[T] {
s := make(map[T]struct{}, len(items))
for i := range items {
s[items[i]] = struct{}{}
}
return s
}
func (s Set[T]) Has(v T) bool {
_, ok := (s)[v]
return ok
}
func (s Set[T]) Add(items ...T) Set[T] {
for _, i := range items {
s[i] = struct{}{}
}
return s
}
func (s Set[T]) Delete(items ...T) Set[T] {
for _, i := range items {
delete(s, i)
}
return s
}
func (s Set[T]) Equal(e Set[T]) bool {
for k := range s {
if _, ok := e[k]; !ok {
return false
}
}
for k := range e {
if _, ok := s[k]; !ok {
return false
}
}
return true
}
func (s Set[T]) String() string {
if s == nil {
return "set(<nil>)"
}
lis := make([]string, 0, len(s))
for k := range s {
lis = append(lis, fmt.Sprint(k))
}
var b strings.Builder
b.WriteString("set(")
b.WriteString(strings.Join(lis, ","))
b.WriteString(")")
return b.String()
}
type ordered interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64
}
type BoundSet[T ordered] struct {
min, max T
s Set[T]
}
func NewBoundSet[T ordered](min, max T, items ...T) *BoundSet[T] {
b := &BoundSet[T]{
min: min,
max: max,
s: New[T](),
}
b.Add(items...)
return b
}
func (l *BoundSet[T]) Add(items ...T) *BoundSet[T] {
n := 0
for i := range items {
if items[i] >= l.min && items[i] <= l.max {
items[n] = items[i]
n++
}
}
l.s.Add(items[:n]...)
return l
}
func (l *BoundSet[T]) AddRange(min, max T) {
min = math.Max(min, l.min)
max = math.Min(max, l.max)
var lis []T
for ; min <= max; min++ {
lis = append(lis, min)
}
l.s.Add(lis...)
}
func (l *BoundSet[T]) Delete(items ...T) *BoundSet[T] {
n := 0
for i := range items {
if items[i] >= l.min && items[i] <= l.max {
items[n] = items[i]
n++
}
}
l.s.Delete(items[:n]...)
return l
}
func (l *BoundSet[T]) Has(v T) bool {
return l.s.Has(v)
}
func (l *BoundSet[T]) String() string {
lis := make([]string, len(l.s))
n := 0
for k := range l.s {
lis[n] = fmt.Sprint(k)
n++
}
sort.Strings(lis)
var b strings.Builder
b.WriteString("set(")
b.WriteString(strings.Join(lis, ","))
b.WriteString(")")
return b.String()
}

View File

@ -1,39 +0,0 @@
package set_test
import (
"strings"
"testing"
"github.com/matryer/is"
"go.sour.is/ev/pkg/set"
)
func TestStringSet(t *testing.T) {
is := is.New(t)
s := set.New(strings.Fields("one two three")...)
is.True(s.Has("one"))
is.True(s.Has("two"))
is.True(s.Has("three"))
is.True(!s.Has("four"))
is.Equal(set.New("one").String(), "set(one)")
var n set.Set[string]
is.Equal(n.String(), "set(<nil>)")
}
func TestBoundSet(t *testing.T) {
is := is.New(t)
s := set.NewBoundSet(1, 100, 1, 2, 3, 100, 1001)
is.True(s.Has(1))
is.True(s.Has(2))
is.True(s.Has(3))
is.True(!s.Has(1001))
is.Equal(set.NewBoundSet(1, 100, 1).String(), "set(1)")
}

View File

@ -1,163 +0,0 @@
package slice
import (
"go.sour.is/ev/pkg/math"
)
// FilterType returns a subset that matches the type.
func FilterType[T any](in ...any) []T {
lis := make([]T, 0, len(in))
for _, u := range in {
if t, ok := u.(T); ok {
lis = append(lis, t)
}
}
return lis
}
func FilterFn[T any](fn func(T) bool, in ...T) []T {
lis := make([]T, 0, len(in))
for _, t := range in {
if fn(t) {
lis = append(lis, t)
}
}
return lis
}
// Find returns the first of type found. or false if not found.
func Find[T any](in ...any) (T, bool) {
return First(FilterType[T](in...)...)
}
func FindFn[T any](fn func(T) bool, in ...T) (T, bool) {
return First(FilterFn(fn, in...)...)
}
// First returns the first element in a slice.
func First[T any](in ...T) (T, bool) {
if len(in) == 0 {
var zero T
return zero, false
}
return in[0], true
}
// Map applys func to each element s and returns results as slice.
func Map[T, U any](f func(int, T) U) func(...T) []U {
return func(lis ...T) []U {
r := make([]U, len(lis))
for i, v := range lis {
r[i] = f(i, v)
}
return r
}
}
func Reduce[T, R any](r R, fn func(T, R, int) R) func(...T) R {
return func(lis ...T) R {
for i, t := range lis {
r = fn(t, r, i)
}
return r
}
}
type Pair[K comparable, V any] struct {
Key K
Value V
}
func FromMap[K comparable, V any](m map[K]V) (keys []K, values []V) {
if m == nil {
return nil, nil
}
keys = FromMapKeys(m)
return keys, FromMapValues(m, keys)
}
func FromMapKeys[K comparable, V any](m map[K]V) (keys []K) {
if m == nil {
return nil
}
keys = make([]K, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}
func FromMapValues[K comparable, V any](m map[K]V, keys []K) (values []V) {
if m == nil {
return nil
}
values = make([]V, 0, len(keys))
for _, k := range keys {
values = append(values, m[k])
}
return values
}
func ToMap[K comparable, V any](keys []K, values []V) (m map[K]V) {
m = make(map[K]V, len(keys))
for i := range keys {
if len(values) < i {
break
}
m[keys[i]] = values[i]
}
return m
}
func Zip[K comparable, V any](k []K, v []V) []Pair[K, V] {
lis := make([]Pair[K, V], math.Max(len(k), len(v)))
for i := range lis {
if k != nil && len(k) > i {
lis[i].Key = k[i]
}
if v != nil && len(v) > i {
lis[i].Value = v[i]
}
}
return lis
}
func Align[T any](k []T, v []T, less func(T, T) bool) []Pair[*T, *T] {
lis := make([]Pair[*T, *T], 0, math.Max(len(k), len(v)))
var j int
for i := 0; i < len(k); {
if j >= len(v) || less(k[i], v[j]) {
lis = append(lis, Pair[*T, *T]{&k[i], nil})
i++
continue
}
if less(v[j], k[i]) {
lis = append(lis, Pair[*T, *T]{nil, &v[j]})
j++
continue
}
lis = append(lis, Pair[*T, *T]{&k[i], &v[j]})
i++
j++
}
for ; j < len(v); j++ {
lis = append(lis, Pair[*T, *T]{nil, &v[j]})
}
return lis
}

View File

@ -1,53 +0,0 @@
package slice_test
import (
"testing"
"github.com/matryer/is"
"go.sour.is/ev/pkg/slice"
)
func TestAlign(t *testing.T) {
type testCase struct {
left, right []string
combined []slice.Pair[*string, *string]
}
tests := []testCase{
{
left: []string{"1", "3", "5"},
right: []string{"2", "3", "4"},
combined: []slice.Pair[*string, *string]{
{ptr("1"), nil},
{nil, ptr("2")},
{ptr("3"), ptr("3")},
{nil, ptr("4")},
{ptr("5"), nil},
},
},
{
left: []string{"2", "3", "4"},
right: []string{"1", "3", "5"},
combined: []slice.Pair[*string, *string]{
{nil, ptr("1")},
{ptr("2"), nil},
{ptr("3"), ptr("3")},
{ptr("4"), nil},
{nil, ptr("5")},
},
},
}
is := is.New(t)
for _, tt := range tests {
combined := slice.Align(tt.left, tt.right, func(l, r string) bool { return l < r })
is.Equal(len(combined), len(tt.combined))
for i := range combined {
is.Equal(combined[i], tt.combined[i])
}
}
}
func ptr[T any](v T) *T { return &v }