mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-10-31 22:18:52 +00:00
Merge branch 'main' into bugfix/error-string-typo
This commit is contained in:
commit
23c04e241b
397 changed files with 15484 additions and 14726 deletions
16
.drone.yml
16
.drone.yml
|
@ -12,7 +12,7 @@ steps:
|
|||
# We use golangci-lint for linting.
|
||||
# See: https://golangci-lint.run/
|
||||
- name: lint
|
||||
image: golangci/golangci-lint:v1.55.0
|
||||
image: golangci/golangci-lint:v1.57.2
|
||||
volumes:
|
||||
- name: go-build-cache
|
||||
path: /root/.cache/go-build
|
||||
|
@ -28,7 +28,7 @@ steps:
|
|||
- pull_request
|
||||
|
||||
- name: test
|
||||
image: golang:1.21-alpine
|
||||
image: golang:1.22-alpine
|
||||
volumes:
|
||||
- name: go-build-cache
|
||||
path: /root/.cache/go-build
|
||||
|
@ -80,7 +80,7 @@ steps:
|
|||
- yarn --cwd ./web/source build
|
||||
|
||||
- name: snapshot
|
||||
image: superseriousbusiness/gotosocial-drone-build:0.4.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
|
||||
image: superseriousbusiness/gotosocial-drone-build:0.6.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
|
||||
volumes:
|
||||
- name: go-build-cache
|
||||
path: /root/.cache/go-build
|
||||
|
@ -99,7 +99,7 @@ steps:
|
|||
commands:
|
||||
# Create a snapshot build with GoReleaser.
|
||||
- git fetch --tags
|
||||
- goreleaser release --rm-dist --snapshot
|
||||
- goreleaser release --clean --snapshot
|
||||
|
||||
# Login to Docker, push Docker image snapshots + manifests.
|
||||
- /go/dockerlogin.sh
|
||||
|
@ -121,7 +121,7 @@ steps:
|
|||
- main
|
||||
|
||||
- name: release
|
||||
image: superseriousbusiness/gotosocial-drone-build:0.4.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
|
||||
image: superseriousbusiness/gotosocial-drone-build:0.6.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
|
||||
volumes:
|
||||
- name: go-build-cache
|
||||
path: /root/.cache/go-build
|
||||
|
@ -136,7 +136,7 @@ steps:
|
|||
commands:
|
||||
- git fetch --tags
|
||||
- /go/dockerlogin.sh
|
||||
- goreleaser release --rm-dist
|
||||
- goreleaser release --clean
|
||||
when:
|
||||
event:
|
||||
include:
|
||||
|
@ -180,7 +180,7 @@ clone:
|
|||
|
||||
steps:
|
||||
- name: mirror
|
||||
image: superseriousbusiness/gotosocial-drone-build:0.4.0
|
||||
image: superseriousbusiness/gotosocial-drone-build:0.6.0
|
||||
environment:
|
||||
ORIGIN_REPO: https://github.com/superseriousbusiness/gotosocial
|
||||
TARGET_REPO: https://codeberg.org/superseriousbusiness/gotosocial
|
||||
|
@ -193,6 +193,6 @@ steps:
|
|||
|
||||
---
|
||||
kind: signature
|
||||
hmac: 4789cebf9156b2c3cb0f097311ea7620e709e4332f130dcae51a938515dc952e
|
||||
hmac: c07f32c63cbb8180c1a37e46ff1362c1c45586819b52c6de67366ae3504314e4
|
||||
|
||||
...
|
||||
|
|
11
.vscode/settings.json
vendored
11
.vscode/settings.json
vendored
|
@ -10,5 +10,14 @@
|
|||
},
|
||||
"eslint.workingDirectories": ["web/source"],
|
||||
"eslint.lintTask.enable": true,
|
||||
"eslint.lintTask.options": "${workspaceFolder}/web/source"
|
||||
"eslint.lintTask.options": "${workspaceFolder}/web/source",
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"typescriptreact"
|
||||
],
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
}
|
|
@ -2,11 +2,11 @@
|
|||
# Dockerfile reference: https://docs.docker.com/engine/reference/builder/
|
||||
|
||||
# stage 1: generate up-to-date swagger.yaml to put in the final container
|
||||
FROM --platform=${BUILDPLATFORM} golang:1.21-alpine AS swagger
|
||||
FROM --platform=${BUILDPLATFORM} golang:1.22-alpine AS swagger
|
||||
|
||||
RUN \
|
||||
### Installs goswagger for building swagger definitions inside this container
|
||||
go install "github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5" && \
|
||||
go install "github.com/go-swagger/go-swagger/cmd/swagger@c46c303aaa02" && \
|
||||
# Makes swagger executable
|
||||
chmod +x /go/bin/swagger
|
||||
|
||||
|
@ -28,7 +28,7 @@ RUN yarn --cwd ./web/source install && \
|
|||
rm -rf ./web/source
|
||||
|
||||
# stage 3: build the executor container
|
||||
FROM --platform=${TARGETPLATFORM} alpine:3.17.2 as executor
|
||||
FROM --platform=${TARGETPLATFORM} alpine:3.19.1 as executor
|
||||
|
||||
# switch to non-root user:group for GtS
|
||||
USER 1000:1000
|
||||
|
|
|
@ -277,10 +277,11 @@ The following open source libraries, frameworks, and tools are used by GoToSocia
|
|||
- [gruf/go-cache](https://codeberg.org/gruf/go-cache); LRU and TTL caches. [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-debug](https://codeberg.org/gruf/go-debug); debug build tag. [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-errors](https://codeberg.org/gruf/go-errors); context-like error w/ value wrapping [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-fastcopy](https://codeberg.org/gruf/go-fastcopy); performant pooled I/O copying [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-fastcopy](https://codeberg.org/gruf/go-fastcopy); performant (buffer pooled) I/O copying [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-kv](https://codeberg.org/gruf/go-kv); log field formatting. [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-list](https://codeberg.org/gruf/go-list); generic doubly linked list. [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-mutexes](https://codeberg.org/gruf/go-mutexes); safemutex & mutex map. [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-runners](https://codeberg.org/gruf/go-runners); workerpools and synchronization. [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-runners](https://codeberg.org/gruf/go-runners); synchronization utilities. [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-sched](https://codeberg.org/gruf/go-sched); task scheduler. [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-store](https://codeberg.org/gruf/go-store); file storage backend (local & s3). [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
- [gruf/go-structr](https://codeberg.org/gruf/go-structr); struct caching + queueing with automated indexing by field. [MIT License](https://spdx.org/licenses/MIT.html).
|
||||
|
|
|
@ -39,7 +39,6 @@ func initState(ctx context.Context) (*state.State, error) {
|
|||
var state state.State
|
||||
state.Caches.Init()
|
||||
state.Caches.Start()
|
||||
state.Workers.Start()
|
||||
|
||||
// Set the state DB connection
|
||||
dbConn, err := bundb.NewBunDBService(ctx, &state)
|
||||
|
|
|
@ -44,7 +44,10 @@ func setupPrune(ctx context.Context) (*prune, error) {
|
|||
state.Caches.Init()
|
||||
state.Caches.Start()
|
||||
|
||||
state.Workers.Start()
|
||||
// Scheduler is required for the
|
||||
// claner, but no other workers
|
||||
// are needed for this CLI action.
|
||||
state.Workers.StartScheduler()
|
||||
|
||||
dbService, err := bundb.NewBunDBService(ctx, &state)
|
||||
if err != nil {
|
||||
|
|
|
@ -35,6 +35,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/filter/spam"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/visibility"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/metrics"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/middleware"
|
||||
tlprocessor "github.com/superseriousbusiness/gotosocial/internal/processing/timeline"
|
||||
|
@ -128,25 +129,6 @@ var Start action.GTSAction = func(ctx context.Context) error {
|
|||
TLSInsecureSkipVerify: config.GetHTTPClientTLSInsecureSkipVerify(),
|
||||
})
|
||||
|
||||
// Initialize delivery worker with http client.
|
||||
state.Workers.Delivery.Init(client)
|
||||
|
||||
// Initialize workers.
|
||||
state.Workers.Start()
|
||||
defer state.Workers.Stop()
|
||||
|
||||
// Add a task to the scheduler to sweep caches.
|
||||
// Frequency = 1 * minute
|
||||
// Threshold = 80% capacity
|
||||
_ = state.Workers.Scheduler.AddRecurring(
|
||||
"@cachesweep", // id
|
||||
time.Time{}, // start
|
||||
time.Minute, // freq
|
||||
func(context.Context, time.Time) {
|
||||
state.Caches.Sweep(60)
|
||||
},
|
||||
)
|
||||
|
||||
// Build handlers used in later initializations.
|
||||
mediaManager := media.NewManager(&state)
|
||||
oauthServer := oauth.New(ctx, dbService)
|
||||
|
@ -195,10 +177,27 @@ var Start action.GTSAction = func(ctx context.Context) error {
|
|||
return fmt.Errorf("error starting list timeline: %s", err)
|
||||
}
|
||||
|
||||
// Create a media cleaner using the given state.
|
||||
// Start the job scheduler
|
||||
// (this is required for cleaner).
|
||||
state.Workers.StartScheduler()
|
||||
|
||||
// Add a task to the scheduler to sweep caches.
|
||||
// Frequency = 1 * minute
|
||||
// Threshold = 60% capacity
|
||||
_ = state.Workers.Scheduler.AddRecurring(
|
||||
"@cachesweep", // id
|
||||
time.Time{}, // start
|
||||
time.Minute, // freq
|
||||
func(context.Context, time.Time) {
|
||||
state.Caches.Sweep(60)
|
||||
},
|
||||
)
|
||||
|
||||
// Create background cleaner.
|
||||
cleaner := cleaner.New(&state)
|
||||
|
||||
// Create the processor using all the other services we've created so far.
|
||||
// Create the processor using all the
|
||||
// other services we've created so far.
|
||||
processor := processing.NewProcessor(
|
||||
cleaner,
|
||||
typeConverter,
|
||||
|
@ -209,13 +208,16 @@ var Start action.GTSAction = func(ctx context.Context) error {
|
|||
emailSender,
|
||||
)
|
||||
|
||||
// Set state client / federator asynchronous worker enqueue functions
|
||||
state.Workers.EnqueueClientAPI = processor.Workers().EnqueueClientAPI
|
||||
state.Workers.EnqueueFediAPI = processor.Workers().EnqueueFediAPI
|
||||
// Initialize the specialized workers.
|
||||
state.Workers.Client.Init(messages.ClientMsgIndices())
|
||||
state.Workers.Federator.Init(messages.FederatorMsgIndices())
|
||||
state.Workers.Delivery.Init(client)
|
||||
state.Workers.Client.Process = processor.Workers().ProcessFromClientAPI
|
||||
state.Workers.Federator.Process = processor.Workers().ProcessFromFediAPI
|
||||
|
||||
// Set state client / federator synchronous processing functions.
|
||||
state.Workers.ProcessFromClientAPI = processor.Workers().ProcessFromClientAPI
|
||||
state.Workers.ProcessFromFediAPI = processor.Workers().ProcessFromFediAPI
|
||||
// Initialize workers.
|
||||
state.Workers.Start()
|
||||
defer state.Workers.Stop()
|
||||
|
||||
// Schedule tasks for all existing poll expiries.
|
||||
if err := processor.Polls().ScheduleAll(ctx); err != nil {
|
||||
|
|
47
go.mod
47
go.mod
|
@ -1,10 +1,10 @@
|
|||
module github.com/superseriousbusiness/gotosocial
|
||||
|
||||
go 1.21
|
||||
go 1.22
|
||||
|
||||
replace modernc.org/sqlite => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.8-concurrency-workaround
|
||||
|
||||
toolchain go1.21.3
|
||||
toolchain go1.22.2
|
||||
|
||||
require (
|
||||
codeberg.org/gruf/go-bytes v1.0.2
|
||||
|
@ -16,12 +16,13 @@ require (
|
|||
codeberg.org/gruf/go-fastcopy v1.1.2
|
||||
codeberg.org/gruf/go-iotools v0.0.0-20230811115124-5d4223615a7f
|
||||
codeberg.org/gruf/go-kv v1.6.4
|
||||
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f
|
||||
codeberg.org/gruf/go-logger/v2 v2.2.1
|
||||
codeberg.org/gruf/go-mutexes v1.4.1
|
||||
codeberg.org/gruf/go-runners v1.6.2
|
||||
codeberg.org/gruf/go-sched v1.2.3
|
||||
codeberg.org/gruf/go-store/v2 v2.2.4
|
||||
codeberg.org/gruf/go-structr v0.6.2
|
||||
codeberg.org/gruf/go-structr v0.7.0
|
||||
codeberg.org/superseriousbusiness/exif-terminator v0.7.0
|
||||
github.com/DmitriyVTitov/size v1.5.0
|
||||
github.com/KimMachineGun/automemlimit v0.6.0
|
||||
|
@ -34,7 +35,7 @@ require (
|
|||
github.com/gin-contrib/sessions v1.0.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/go-playground/form/v4 v4.2.1
|
||||
github.com/go-swagger/go-swagger v0.30.5
|
||||
github.com/go-swagger/go-swagger v0.30.6-0.20240418033037-c46c303aaa02
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/feeds v1.1.2
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
|
@ -89,7 +90,7 @@ require (
|
|||
codeberg.org/gruf/go-mangler v1.3.0 // indirect
|
||||
codeberg.org/gruf/go-maps v1.0.3 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
|
@ -111,7 +112,7 @@ require (
|
|||
github.com/dsoprea/go-photoshop-info-format v0.0.0-20200610045659-121dd752914d // indirect
|
||||
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
|
@ -120,17 +121,17 @@ require (
|
|||
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.21.4 // indirect
|
||||
github.com/go-openapi/errors v0.20.4 // indirect
|
||||
github.com/go-openapi/inflect v0.19.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/loads v0.21.2 // indirect
|
||||
github.com/go-openapi/runtime v0.26.0 // indirect
|
||||
github.com/go-openapi/spec v0.20.9 // indirect
|
||||
github.com/go-openapi/strfmt v0.21.7 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/go-openapi/validate v0.22.1 // indirect
|
||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.0 // indirect
|
||||
github.com/go-openapi/inflect v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/loads v0.22.0 // indirect
|
||||
github.com/go-openapi/runtime v0.28.0 // indirect
|
||||
github.com/go-openapi/spec v0.21.0 // indirect
|
||||
github.com/go-openapi/strfmt v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-openapi/validate v0.24.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.19.0 // indirect
|
||||
|
@ -141,14 +142,14 @@ require (
|
|||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
|
||||
github.com/gorilla/context v1.1.2 // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/handlers v1.5.2 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
github.com/gorilla/sessions v1.2.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/huandu/xstrings v1.3.3 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
|
@ -183,11 +184,11 @@ require (
|
|||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/rs/xid v1.5.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
|
@ -209,7 +210,7 @@ require (
|
|||
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/arch v0.7.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
|
|
195
go.sum
195
go.sum
|
@ -56,6 +56,8 @@ codeberg.org/gruf/go-iotools v0.0.0-20230811115124-5d4223615a7f h1:Kazm/PInN2m1S
|
|||
codeberg.org/gruf/go-iotools v0.0.0-20230811115124-5d4223615a7f/go.mod h1:B8uq4yHtIcKXhBZT9C/SYisz25lldLHMVpwZPz4ADLQ=
|
||||
codeberg.org/gruf/go-kv v1.6.4 h1:3NZiW8HVdBM3kpOiLb7XfRiihnzZWMAixdCznguhILk=
|
||||
codeberg.org/gruf/go-kv v1.6.4/go.mod h1:O/YkSvKiS9XsRolM3rqCd9YJmND7dAXu9z+PrlYO4bc=
|
||||
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f h1:Ss6Z+vygy+jOGhj96d/GwsYYDd22QmIcH74zM7/nQkw=
|
||||
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f/go.mod h1:F9pl4h34iuVN7kucKam9fLwsItTc+9mmaKt7pNXRd/4=
|
||||
codeberg.org/gruf/go-logger/v2 v2.2.1 h1:RP2u059EQKTBFV3cN8X6xDxNk2RkzqdgXGKflKqB7Oc=
|
||||
codeberg.org/gruf/go-logger/v2 v2.2.1/go.mod h1:m/vBfG5jNUmYXI8Hg9aVSk7Pn8YgEBITQB/B/CzdRss=
|
||||
codeberg.org/gruf/go-loosy v0.0.0-20231007123304-bb910d1ab5c4 h1:IXwfoU7f2whT6+JKIKskNl/hBlmWmnF1vZd84Eb3cyA=
|
||||
|
@ -72,8 +74,8 @@ codeberg.org/gruf/go-sched v1.2.3 h1:H5ViDxxzOBR3uIyGBCf0eH8b1L8wMybOXcdtUUTXZHk
|
|||
codeberg.org/gruf/go-sched v1.2.3/go.mod h1:vT9uB6KWFIIwnG9vcPY2a0alYNoqdL1mSzRM8I+PK7A=
|
||||
codeberg.org/gruf/go-store/v2 v2.2.4 h1:8HO1Jh2gg7boQKA3hsDAIXd9zwieu5uXwDXEcTOD9js=
|
||||
codeberg.org/gruf/go-store/v2 v2.2.4/go.mod h1:zI4VWe5CpXAktYMtaBMrgA5QmO0sQH53LBRvfn1huys=
|
||||
codeberg.org/gruf/go-structr v0.6.2 h1:1zs7UkPBsRGRDMHhrfFL7GrwAyPHxFXCchu8ADv/zuM=
|
||||
codeberg.org/gruf/go-structr v0.6.2/go.mod h1:K1FXkUyO6N/JKt8aWqyQ8rtW7Z9ZmXKWP8mFAQ2OJjE=
|
||||
codeberg.org/gruf/go-structr v0.7.0 h1:gy0/wD7718HwJDoBMeMumk4+7veLrkumgCEOnCyzS8w=
|
||||
codeberg.org/gruf/go-structr v0.7.0/go.mod h1:K1FXkUyO6N/JKt8aWqyQ8rtW7Z9ZmXKWP8mFAQ2OJjE=
|
||||
codeberg.org/superseriousbusiness/exif-terminator v0.7.0 h1:Y6VApSXhKqExG0H2hZ2JelRK4xmWdjDQjn13CpEfzko=
|
||||
codeberg.org/superseriousbusiness/exif-terminator v0.7.0/go.mod h1:gCWKduudUWFzsnixoMzu0FYVdxHWG+AbXnZ50DqxsUE=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
|
@ -85,12 +87,11 @@ github.com/KimMachineGun/automemlimit v0.6.0 h1:p/BXkH+K40Hax+PuWWPQ478hPjsp9h1C
|
|||
github.com/KimMachineGun/automemlimit v0.6.0/go.mod h1:T7xYht7B8r6AG/AqFcUdc7fzd2bIdBKmepfP2S1svPY=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
|
||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/abema/go-mp4 v1.2.0 h1:gi4X8xg/m179N/J15Fn5ugywN9vtI6PLk6iLldHGLAk=
|
||||
github.com/abema/go-mp4 v1.2.0/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws=
|
||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||
|
@ -98,7 +99,6 @@ github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY
|
|||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
|
@ -176,9 +176,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
|||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
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.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
|
@ -218,46 +217,28 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
|||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
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-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY=
|
||||
github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc=
|
||||
github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo=
|
||||
github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
||||
github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
||||
github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
||||
github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M=
|
||||
github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk=
|
||||
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
|
||||
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g=
|
||||
github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro=
|
||||
github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw=
|
||||
github.com/go-openapi/runtime v0.26.0 h1:HYOFtG00FM1UvqrcxbEJg/SwvDRvYLQKGhw2zaQjTcc=
|
||||
github.com/go-openapi/runtime v0.26.0/go.mod h1:QgRGeZwrUcSHdeh4Ka9Glvo0ug1LC5WyE+EV88plZrQ=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||
github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
|
||||
github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||
github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg=
|
||||
github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
|
||||
github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg=
|
||||
github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k=
|
||||
github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU=
|
||||
github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
|
||||
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
|
||||
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
|
||||
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
|
||||
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
|
||||
github.com/go-openapi/inflect v0.21.0 h1:FoBjBTQEcbg2cJUWX6uwL9OyIW8eqc9k4KhN4lfbeYk=
|
||||
github.com/go-openapi/inflect v0.21.0/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
|
||||
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
|
||||
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
|
||||
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
|
||||
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
|
||||
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
|
||||
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
|
||||
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
|
||||
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
|
@ -270,39 +251,12 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91
|
|||
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
|
||||
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-swagger/go-swagger v0.30.5 h1:SQ2+xSonWjjoEMOV5tcOnZJVlfyUfCBhGQGArS1b9+U=
|
||||
github.com/go-swagger/go-swagger v0.30.5/go.mod h1:cWUhSyCNqV7J1wkkxfr5QmbcnCewetCdvEXqgPvbc/Q=
|
||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0=
|
||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0=
|
||||
github.com/go-swagger/go-swagger v0.30.6-0.20240418033037-c46c303aaa02 h1:J6YiT/eg3gAfKMdVCkWXe6khsO+nxa8W4URZ4AUqzbA=
|
||||
github.com/go-swagger/go-swagger v0.30.6-0.20240418033037-c46c303aaa02/go.mod h1:i1/E+d8iPNReSE7y04FaVu5OPKB3il5cn+T1Egogg3I=
|
||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850 h1:PSPmmucxGiFBtbQcttHTUc4LQ3P09AW+ldO2qspyKdY=
|
||||
github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
|
||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
||||
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
|
||||
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
|
||||
github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
|
||||
github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
|
||||
github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
|
||||
github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
|
||||
github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
|
||||
github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
|
||||
github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
|
||||
github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
|
||||
github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
|
||||
github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
|
||||
github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
|
||||
github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
|
||||
github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
|
||||
github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
|
||||
github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
|
||||
github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
|
||||
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
|
||||
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
|
||||
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
||||
|
@ -342,7 +296,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
|||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
|
@ -352,7 +305,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/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.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
|
@ -386,8 +338,8 @@ github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
|||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/gorilla/feeds v1.1.2 h1:pxzZ5PD3RJdhFH2FsJJ4x6PqMqbgFk1+Vez4XWBW8Iw=
|
||||
github.com/gorilla/feeds v1.1.2/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
|
||||
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
|
||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
||||
|
@ -406,15 +358,15 @@ github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf
|
|||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
|
||||
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
|
@ -430,7 +382,6 @@ github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LF
|
|||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
|
@ -440,12 +391,9 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
|
|||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
|
@ -453,10 +401,7 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
|
|||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
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.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
|
@ -468,13 +413,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
|||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
|
@ -498,8 +438,6 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1
|
|||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
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/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
|
@ -510,12 +448,10 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
|||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
|
||||
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
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/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
|
@ -530,12 +466,9 @@ github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e h1:s2RNOM/IGd
|
|||
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
|
||||
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
|
@ -556,12 +489,10 @@ github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b h1:aUNXCGgukb4gtY
|
|||
github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
|
@ -572,11 +503,9 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR
|
|||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
|
@ -590,16 +519,13 @@ github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNo
|
|||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
|
@ -691,11 +617,6 @@ github.com/wagslane/go-password-validator v0.3.0 h1:vfxOPzGHkz5S146HDpavl0cw1DSV
|
|||
github.com/wagslane/go-password-validator v0.3.0/go.mod h1:TI1XJ6T5fRdRnHqHt14pvy1tNVnrwe7m3/f1f2fDphQ=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
|
@ -704,7 +625,6 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
|
|||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
|
||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
|
||||
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
|
||||
|
@ -718,9 +638,6 @@ github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U=
|
|||
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.8-concurrency-workaround h1:ESobxED9bfE0nOQP/WPv9+tMR8oZoDIWRKlNK2Vs4Ms=
|
||||
gitlab.com/NyaaaWhatsUpDoc/sqlite v1.29.8-concurrency-workaround/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk=
|
||||
go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg=
|
||||
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
|
||||
go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
|
||||
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
||||
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
|
@ -757,16 +674,12 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
|
|||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
|
||||
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
|
@ -780,8 +693,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
|
@ -838,8 +751,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
|
|||
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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
|
@ -856,27 +767,20 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/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-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -903,8 +807,6 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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=
|
||||
|
@ -924,8 +826,6 @@ 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.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.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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
|
@ -940,13 +840,9 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
|
|||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
|
@ -1071,7 +967,6 @@ google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh
|
|||
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-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
|
@ -1091,9 +986,7 @@ 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/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-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
@ -72,7 +72,6 @@ func (suite *StatusStandardTestSuite) SetupSuite() {
|
|||
|
||||
func (suite *StatusStandardTestSuite) SetupTest() {
|
||||
suite.state.Caches.Init()
|
||||
testrig.StartNoopWorkers(&suite.state)
|
||||
|
||||
testrig.InitTestConfig()
|
||||
testrig.InitTestLog()
|
||||
|
@ -98,6 +97,8 @@ func (suite *StatusStandardTestSuite) SetupTest() {
|
|||
suite.emailSender = testrig.NewEmailSender("../../../../web/template/", nil)
|
||||
suite.processor = testrig.NewTestProcessor(&suite.state, suite.federator, suite.emailSender, suite.mediaManager)
|
||||
suite.statusModule = statuses.New(suite.processor)
|
||||
|
||||
testrig.StartWorkers(&suite.state, suite.processor.Workers())
|
||||
}
|
||||
|
||||
func (suite *StatusStandardTestSuite) TearDownTest() {
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
|
@ -69,7 +69,7 @@ func (suite *StatusDeleteTestSuite) TestPostDelete() {
|
|||
|
||||
result := recorder.Result()
|
||||
defer result.Body.Close()
|
||||
b, err := ioutil.ReadAll(result.Body)
|
||||
b, err := io.ReadAll(result.Body)
|
||||
suite.NoError(err)
|
||||
|
||||
statusReply := &apimodel.Status{}
|
||||
|
|
|
@ -104,7 +104,7 @@ func (d *Dereferencer) GetAccountByURI(ctx context.Context, requestUser string,
|
|||
|
||||
if accountable != nil {
|
||||
// This account was updated, enqueue re-dereference featured posts.
|
||||
d.state.Workers.Federator.MustEnqueueCtx(ctx, func(ctx context.Context) {
|
||||
d.state.Workers.Dereference.Queue.Push(func(ctx context.Context) {
|
||||
if err := d.dereferenceAccountFeatured(ctx, requestUser, account); err != nil {
|
||||
log.Errorf(ctx, "error fetching account featured collection: %v", err)
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ func (d *Dereferencer) GetAccountByUsernameDomain(ctx context.Context, requestUs
|
|||
|
||||
if accountable != nil {
|
||||
// This account was updated, enqueue re-dereference featured posts.
|
||||
d.state.Workers.Federator.MustEnqueueCtx(ctx, func(ctx context.Context) {
|
||||
d.state.Workers.Dereference.Queue.Push(func(ctx context.Context) {
|
||||
if err := d.dereferenceAccountFeatured(ctx, requestUser, account); err != nil {
|
||||
log.Errorf(ctx, "error fetching account featured collection: %v", err)
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ func (d *Dereferencer) RefreshAccount(
|
|||
|
||||
if accountable != nil {
|
||||
// This account was updated, enqueue re-dereference featured posts.
|
||||
d.state.Workers.Federator.MustEnqueueCtx(ctx, func(ctx context.Context) {
|
||||
d.state.Workers.Dereference.Queue.Push(func(ctx context.Context) {
|
||||
if err := d.dereferenceAccountFeatured(ctx, requestUser, latest); err != nil {
|
||||
log.Errorf(ctx, "error fetching account featured collection: %v", err)
|
||||
}
|
||||
|
@ -362,7 +362,7 @@ func (d *Dereferencer) RefreshAccountAsync(
|
|||
}
|
||||
|
||||
// Enqueue a worker function to enrich this account async.
|
||||
d.state.Workers.Federator.MustEnqueueCtx(ctx, func(ctx context.Context) {
|
||||
d.state.Workers.Dereference.Queue.Push(func(ctx context.Context) {
|
||||
latest, accountable, err := d.enrichAccountSafely(ctx, requestUser, uri, account, accountable)
|
||||
if err != nil {
|
||||
log.Errorf(ctx, "error enriching remote account: %v", err)
|
||||
|
|
|
@ -255,7 +255,7 @@ func (d *Dereferencer) RefreshStatusAsync(
|
|||
}
|
||||
|
||||
// Enqueue a worker function to re-fetch this status entirely async.
|
||||
d.state.Workers.Federator.MustEnqueueCtx(ctx, func(ctx context.Context) {
|
||||
d.state.Workers.Dereference.Queue.Push(func(ctx context.Context) {
|
||||
latest, statusable, _, err := d.enrichStatusSafely(ctx,
|
||||
requestUser,
|
||||
uri,
|
||||
|
|
|
@ -56,14 +56,14 @@ func (d *Dereferencer) dereferenceThread(
|
|||
}
|
||||
|
||||
// Enqueue dereferencing remaining status thread, (children), asychronously .
|
||||
d.state.Workers.Federator.MustEnqueueCtx(ctx, func(ctx context.Context) {
|
||||
d.state.Workers.Dereference.Queue.Push(func(ctx context.Context) {
|
||||
if err := d.DereferenceStatusDescendants(ctx, requestUser, uri, statusable); err != nil {
|
||||
log.Error(ctx, err)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// This is an existing status, dereference the WHOLE thread asynchronously.
|
||||
d.state.Workers.Federator.MustEnqueueCtx(ctx, func(ctx context.Context) {
|
||||
d.state.Workers.Dereference.Queue.Push(func(ctx context.Context) {
|
||||
if err := d.DereferenceStatusAncestors(ctx, requestUser, status); err != nil {
|
||||
log.Error(ctx, err)
|
||||
}
|
||||
|
|
|
@ -89,13 +89,12 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
|
|||
return err
|
||||
}
|
||||
|
||||
// Process side effects asynchronously.
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityAccept,
|
||||
GTSModel: follow,
|
||||
ReceivingAccount: receivingAcct,
|
||||
RequestingAccount: requestingAcct,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityAccept,
|
||||
GTSModel: follow,
|
||||
Receiving: receivingAcct,
|
||||
Requesting: requestingAcct,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -138,13 +137,12 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
|
|||
return err
|
||||
}
|
||||
|
||||
// Process side effects asynchronously.
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityAccept,
|
||||
GTSModel: follow,
|
||||
ReceivingAccount: receivingAcct,
|
||||
RequestingAccount: requestingAcct,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityAccept,
|
||||
GTSModel: follow,
|
||||
Receiving: receivingAcct,
|
||||
Requesting: requestingAcct,
|
||||
})
|
||||
|
||||
continue
|
||||
|
|
|
@ -81,12 +81,12 @@ func (f *federatingDB) Announce(ctx context.Context, announce vocab.ActivityStre
|
|||
}
|
||||
|
||||
// This is a new boost. Process side effects asynchronously.
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: boost,
|
||||
ReceivingAccount: receivingAcct,
|
||||
RequestingAccount: requestingAcct,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: boost,
|
||||
Receiving: receivingAcct,
|
||||
Requesting: requestingAcct,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
|
|
@ -19,6 +19,7 @@ package federatingdb_test
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/superseriousbusiness/activity/streams/vocab"
|
||||
|
@ -42,7 +43,7 @@ func (suite *AnnounceTestSuite) TestNewAnnounce() {
|
|||
suite.NoError(err)
|
||||
|
||||
// should be a message heading to the processor now, which we can intercept here
|
||||
msg := <-suite.fromFederator
|
||||
msg, _ := suite.getFederatorMsg(5 * time.Second)
|
||||
suite.Equal(ap.ActivityAnnounce, msg.APObjectType)
|
||||
suite.Equal(ap.ActivityCreate, msg.APActivityType)
|
||||
|
||||
|
@ -69,7 +70,7 @@ func (suite *AnnounceTestSuite) TestAnnounceTwice() {
|
|||
suite.NoError(err)
|
||||
|
||||
// should be a message heading to the processor now, which we can intercept here
|
||||
msg := <-suite.fromFederator
|
||||
msg, _ := suite.getFederatorMsg(5 * time.Second)
|
||||
suite.Equal(ap.ActivityAnnounce, msg.APObjectType)
|
||||
suite.Equal(ap.ActivityCreate, msg.APActivityType)
|
||||
boost, ok := msg.GTSModel.(*gtsmodel.Status)
|
||||
|
@ -94,7 +95,8 @@ func (suite *AnnounceTestSuite) TestAnnounceTwice() {
|
|||
|
||||
// since this is a repeat announce with the same URI, just delivered to a different inbox,
|
||||
// we should have nothing in the messages channel...
|
||||
suite.Empty(suite.fromFederator)
|
||||
_, ok = suite.getFederatorMsg(time.Second)
|
||||
suite.False(ok)
|
||||
}
|
||||
|
||||
func TestAnnounceTestSuite(t *testing.T) {
|
||||
|
|
|
@ -99,7 +99,7 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error {
|
|||
BLOCK HANDLERS
|
||||
*/
|
||||
|
||||
func (f *federatingDB) activityBlock(ctx context.Context, asType vocab.Type, receiving *gtsmodel.Account, requestingAccount *gtsmodel.Account) error {
|
||||
func (f *federatingDB) activityBlock(ctx context.Context, asType vocab.Type, receiving *gtsmodel.Account, requesting *gtsmodel.Account) error {
|
||||
blockable, ok := asType.(vocab.ActivityStreamsBlock)
|
||||
if !ok {
|
||||
return errors.New("activityBlock: could not convert type to block")
|
||||
|
@ -110,10 +110,10 @@ func (f *federatingDB) activityBlock(ctx context.Context, asType vocab.Type, rec
|
|||
return fmt.Errorf("activityBlock: could not convert Block to gts model block")
|
||||
}
|
||||
|
||||
if block.AccountID != requestingAccount.ID {
|
||||
if block.AccountID != requesting.ID {
|
||||
return fmt.Errorf(
|
||||
"activityBlock: requestingAccount %s is not Block actor account %s",
|
||||
requestingAccount.URI, block.Account.URI,
|
||||
requesting.URI, block.Account.URI,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -130,12 +130,12 @@ func (f *federatingDB) activityBlock(ctx context.Context, asType vocab.Type, rec
|
|||
return fmt.Errorf("activityBlock: database error inserting block: %s", err)
|
||||
}
|
||||
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityBlock,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: block,
|
||||
ReceivingAccount: receiving,
|
||||
RequestingAccount: requestingAccount,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityBlock,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: block,
|
||||
Receiving: receiving,
|
||||
Requesting: requesting,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
@ -297,7 +297,7 @@ func (f *federatingDB) createPollOptionables(
|
|||
}
|
||||
|
||||
// Enqueue message to the fedi API worker with poll vote(s).
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APActivityType: ap.ActivityCreate,
|
||||
APObjectType: ap.ActivityQuestion,
|
||||
GTSModel: >smodel.PollVote{
|
||||
|
@ -308,8 +308,8 @@ func (f *federatingDB) createPollOptionables(
|
|||
PollID: inReplyTo.PollID,
|
||||
Poll: inReplyTo.Poll,
|
||||
},
|
||||
ReceivingAccount: receiver,
|
||||
RequestingAccount: requester,
|
||||
Receiving: receiver,
|
||||
Requesting: requester,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
@ -377,28 +377,28 @@ func (f *federatingDB) createStatusable(
|
|||
|
||||
// Pass the statusable URI (APIri) into the processor
|
||||
// worker and do the rest of the processing asynchronously.
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
APIri: ap.GetJSONLDId(statusable),
|
||||
APObjectModel: nil,
|
||||
GTSModel: nil,
|
||||
ReceivingAccount: receiver,
|
||||
RequestingAccount: requester,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
APIRI: ap.GetJSONLDId(statusable),
|
||||
APObject: nil,
|
||||
GTSModel: nil,
|
||||
Receiving: receiver,
|
||||
Requesting: requester,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Do the rest of the processing asynchronously. The processor
|
||||
// will handle inserting/updating + further dereferencing the status.
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
APIri: nil,
|
||||
GTSModel: nil,
|
||||
APObjectModel: statusable,
|
||||
ReceivingAccount: receiver,
|
||||
RequestingAccount: requester,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
APIRI: nil,
|
||||
GTSModel: nil,
|
||||
APObject: statusable,
|
||||
Receiving: receiver,
|
||||
Requesting: requester,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
@ -439,12 +439,12 @@ func (f *federatingDB) activityFollow(ctx context.Context, asType vocab.Type, re
|
|||
return fmt.Errorf("activityFollow: database error inserting follow request: %s", err)
|
||||
}
|
||||
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: followRequest,
|
||||
ReceivingAccount: receivingAccount,
|
||||
RequestingAccount: requestingAccount,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: followRequest,
|
||||
Receiving: receivingAccount,
|
||||
Requesting: requestingAccount,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
@ -484,12 +484,12 @@ func (f *federatingDB) activityLike(ctx context.Context, asType vocab.Type, rece
|
|||
return fmt.Errorf("activityLike: database error inserting fave: %w", err)
|
||||
}
|
||||
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityLike,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: fave,
|
||||
ReceivingAccount: receivingAccount,
|
||||
RequestingAccount: requestingAccount,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityLike,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: fave,
|
||||
Receiving: receivingAccount,
|
||||
Requesting: requestingAccount,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
@ -536,12 +536,12 @@ func (f *federatingDB) activityFlag(ctx context.Context, asType vocab.Type, rece
|
|||
return fmt.Errorf("activityFlag: database error inserting report: %w", err)
|
||||
}
|
||||
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFlag,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: report,
|
||||
ReceivingAccount: receivingAccount,
|
||||
RequestingAccount: requestingAccount,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFlag,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: report,
|
||||
Receiving: receivingAccount,
|
||||
Requesting: requestingAccount,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/superseriousbusiness/activity/streams"
|
||||
|
@ -48,10 +49,10 @@ func (suite *CreateTestSuite) TestCreateNote() {
|
|||
suite.NoError(err)
|
||||
|
||||
// should be a message heading to the processor now, which we can intercept here
|
||||
msg := <-suite.fromFederator
|
||||
msg, _ := suite.getFederatorMsg(5 * time.Second)
|
||||
suite.Equal(ap.ObjectNote, msg.APObjectType)
|
||||
suite.Equal(ap.ActivityCreate, msg.APActivityType)
|
||||
suite.Equal(note, msg.APObjectModel)
|
||||
suite.Equal(note, msg.APObject)
|
||||
}
|
||||
|
||||
func (suite *CreateTestSuite) TestCreateNoteForward() {
|
||||
|
@ -79,15 +80,15 @@ func (suite *CreateTestSuite) TestCreateNoteForward() {
|
|||
suite.NoError(err)
|
||||
|
||||
// should be a message heading to the processor now, which we can intercept here
|
||||
msg := <-suite.fromFederator
|
||||
msg, _ := suite.getFederatorMsg(5 * time.Second)
|
||||
suite.Equal(ap.ObjectNote, msg.APObjectType)
|
||||
suite.Equal(ap.ActivityCreate, msg.APActivityType)
|
||||
|
||||
// nothing should be set as the model since this is a forward
|
||||
suite.Nil(msg.APObjectModel)
|
||||
suite.Nil(msg.APObject)
|
||||
|
||||
// but we should have a uri set
|
||||
suite.Equal("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1", msg.APIri.String())
|
||||
suite.Equal("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1", msg.APIRI.String())
|
||||
}
|
||||
|
||||
func (suite *CreateTestSuite) TestCreateFlag1() {
|
||||
|
@ -120,7 +121,7 @@ func (suite *CreateTestSuite) TestCreateFlag1() {
|
|||
}
|
||||
|
||||
// should be a message heading to the processor now, which we can intercept here
|
||||
msg := <-suite.fromFederator
|
||||
msg, _ := suite.getFederatorMsg(5 * time.Second)
|
||||
suite.Equal(ap.ActivityFlag, msg.APObjectType)
|
||||
suite.Equal(ap.ActivityCreate, msg.APActivityType)
|
||||
|
||||
|
|
|
@ -19,10 +19,13 @@ package federatingdb
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/url"
|
||||
|
||||
"codeberg.org/gruf/go-kv"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
)
|
||||
|
@ -34,43 +37,130 @@ import (
|
|||
//
|
||||
// The library makes this call only after acquiring a lock first.
|
||||
func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error {
|
||||
l := log.WithContext(ctx).
|
||||
WithFields(kv.Fields{
|
||||
{"id", id},
|
||||
}...)
|
||||
l.Debug("entering Delete")
|
||||
|
||||
activityContext := getActivityContext(ctx)
|
||||
if activityContext.internal {
|
||||
return nil // Already processed.
|
||||
}
|
||||
|
||||
requestingAcct := activityContext.requestingAcct
|
||||
receivingAcct := activityContext.receivingAcct
|
||||
// Extract receiving / requesting accounts.
|
||||
requesting := activityContext.requestingAcct
|
||||
receiving := activityContext.receivingAcct
|
||||
|
||||
// in a delete we only get the URI, we can't know if we have a status or a profile or something else,
|
||||
// so we have to try a few different things...
|
||||
if s, err := f.state.DB.GetStatusByURI(ctx, id.String()); err == nil && requestingAcct.ID == s.AccountID {
|
||||
l.Debugf("deleting status: %s", s.ID)
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: s,
|
||||
ReceivingAccount: receivingAcct,
|
||||
RequestingAccount: requestingAcct,
|
||||
})
|
||||
// Serialize deleted ID URI.
|
||||
// (may be status OR account)
|
||||
uriStr := id.String()
|
||||
|
||||
var (
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
|
||||
// Try delete as an account URI.
|
||||
ok, err = f.deleteAccount(ctx,
|
||||
requesting,
|
||||
receiving,
|
||||
uriStr,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if ok {
|
||||
// success!
|
||||
return nil
|
||||
}
|
||||
|
||||
if a, err := f.state.DB.GetAccountByURI(ctx, id.String()); err == nil && requestingAcct.ID == a.ID {
|
||||
l.Debugf("deleting account: %s", a.ID)
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: a,
|
||||
ReceivingAccount: receivingAcct,
|
||||
RequestingAccount: requestingAcct,
|
||||
})
|
||||
// Try delete as a status URI.
|
||||
ok, err = f.deleteStatus(ctx,
|
||||
requesting,
|
||||
receiving,
|
||||
uriStr,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if ok {
|
||||
// success!
|
||||
return nil
|
||||
}
|
||||
|
||||
// Log at debug level, as lots of these could indicate federation
|
||||
// issues between remote and this instance, or help with debugging.
|
||||
log.Debugf(ctx, "received delete for unknown target: %s", uriStr)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *federatingDB) deleteAccount(
|
||||
ctx context.Context,
|
||||
requesting *gtsmodel.Account,
|
||||
receiving *gtsmodel.Account,
|
||||
uri string, // target account
|
||||
) (
|
||||
bool, // success?
|
||||
error, // any error
|
||||
) {
|
||||
account, err := f.state.DB.GetAccountByURI(ctx, uri)
|
||||
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
||||
return false, gtserror.Newf("error getting account: %w", err)
|
||||
}
|
||||
|
||||
if account != nil {
|
||||
// Ensure requesting account is
|
||||
// only trying to delete itself.
|
||||
if account.ID != requesting.ID {
|
||||
|
||||
// TODO: handled forwarded deletes,
|
||||
// for now we silently drop this.
|
||||
return true, nil
|
||||
}
|
||||
|
||||
log.Debugf(ctx, "deleting account: %s", account.URI)
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: account,
|
||||
Receiving: receiving,
|
||||
Requesting: requesting,
|
||||
})
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (f *federatingDB) deleteStatus(
|
||||
ctx context.Context,
|
||||
requesting *gtsmodel.Account,
|
||||
receiving *gtsmodel.Account,
|
||||
uri string, // target status
|
||||
) (
|
||||
bool, // success?
|
||||
error, // any error
|
||||
) {
|
||||
status, err := f.state.DB.GetStatusByURI(ctx, uri)
|
||||
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
||||
return false, gtserror.Newf("error getting status: %w", err)
|
||||
}
|
||||
|
||||
if status != nil {
|
||||
// Ensure requesting account is only
|
||||
// trying to delete its own statuses.
|
||||
if status.AccountID != requesting.ID {
|
||||
|
||||
// TODO: handled forwarded deletes,
|
||||
// for now we silently drop this.
|
||||
return true, nil
|
||||
}
|
||||
|
||||
log.Debugf(ctx, "deleting status: %s", status.URI)
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: status,
|
||||
Receiving: receiving,
|
||||
Requesting: requesting,
|
||||
})
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package federatingdb_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
|
@ -34,11 +35,10 @@ import (
|
|||
|
||||
type FederatingDBTestSuite struct {
|
||||
suite.Suite
|
||||
db db.DB
|
||||
tc *typeutils.Converter
|
||||
fromFederator chan messages.FromFediAPI
|
||||
federatingDB federatingdb.DB
|
||||
state state.State
|
||||
db db.DB
|
||||
tc *typeutils.Converter
|
||||
federatingDB federatingdb.DB
|
||||
state state.State
|
||||
|
||||
testTokens map[string]*gtsmodel.Token
|
||||
testClients map[string]*gtsmodel.Client
|
||||
|
@ -51,6 +51,13 @@ type FederatingDBTestSuite struct {
|
|||
testActivities map[string]testrig.ActivityWithSignature
|
||||
}
|
||||
|
||||
func (suite *FederatingDBTestSuite) getFederatorMsg(timeout time.Duration) (*messages.FromFediAPI, bool) {
|
||||
ctx := context.Background()
|
||||
ctx, cncl := context.WithTimeout(ctx, timeout)
|
||||
defer cncl()
|
||||
return suite.state.Workers.Federator.Queue.PopCtx(ctx)
|
||||
}
|
||||
|
||||
func (suite *FederatingDBTestSuite) SetupSuite() {
|
||||
suite.testTokens = testrig.NewTestTokens()
|
||||
suite.testClients = testrig.NewTestClients()
|
||||
|
@ -69,13 +76,6 @@ func (suite *FederatingDBTestSuite) SetupTest() {
|
|||
suite.state.Caches.Init()
|
||||
testrig.StartNoopWorkers(&suite.state)
|
||||
|
||||
suite.fromFederator = make(chan messages.FromFediAPI, 10)
|
||||
suite.state.Workers.EnqueueFediAPI = func(ctx context.Context, msgs ...messages.FromFediAPI) {
|
||||
for _, msg := range msgs {
|
||||
suite.fromFederator <- msg
|
||||
}
|
||||
}
|
||||
|
||||
suite.db = testrig.NewTestDB(&suite.state)
|
||||
|
||||
suite.testActivities = testrig.NewTestActivities(suite.testAccounts)
|
||||
|
@ -96,13 +96,6 @@ func (suite *FederatingDBTestSuite) SetupTest() {
|
|||
func (suite *FederatingDBTestSuite) TearDownTest() {
|
||||
testrig.StandardDBTeardown(suite.db)
|
||||
testrig.StopWorkers(&suite.state)
|
||||
for suite.fromFederator != nil {
|
||||
select {
|
||||
case <-suite.fromFederator:
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createTestContext(receivingAccount *gtsmodel.Account, requestingAccount *gtsmodel.Account) context.Context {
|
||||
|
|
|
@ -170,12 +170,12 @@ func (f *federatingDB) Move(ctx context.Context, move vocab.ActivityStreamsMove)
|
|||
|
||||
// We had a Move already or stored a new Move.
|
||||
// Pass back to a worker for async processing.
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityMove,
|
||||
GTSModel: stubMove,
|
||||
RequestingAccount: requestingAcct,
|
||||
ReceivingAccount: receivingAcct,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityMove,
|
||||
GTSModel: stubMove,
|
||||
Requesting: requestingAcct,
|
||||
Receiving: receivingAcct,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
|
|
@ -27,7 +27,6 @@ import (
|
|||
"github.com/superseriousbusiness/activity/streams/vocab"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
)
|
||||
|
||||
type MoveTestSuite struct {
|
||||
|
@ -78,13 +77,7 @@ func (suite *MoveTestSuite) TestMove() {
|
|||
suite.move(receivingAcct, requestingAcct, moveStr1)
|
||||
|
||||
// Should be a message heading to the processor.
|
||||
var msg messages.FromFediAPI
|
||||
select {
|
||||
case msg = <-suite.fromFederator:
|
||||
// Fine.
|
||||
case <-time.After(5 * time.Second):
|
||||
suite.FailNow("", "timeout waiting for suite.fromFederator")
|
||||
}
|
||||
msg, _ := suite.getFederatorMsg(5 * time.Second)
|
||||
suite.Equal(ap.ObjectProfile, msg.APObjectType)
|
||||
suite.Equal(ap.ActivityMove, msg.APActivityType)
|
||||
|
||||
|
@ -101,12 +94,7 @@ func (suite *MoveTestSuite) TestMove() {
|
|||
|
||||
// Should be a message heading to the processor
|
||||
// since this is just a straight up retry.
|
||||
select {
|
||||
case msg = <-suite.fromFederator:
|
||||
// Fine.
|
||||
case <-time.After(5 * time.Second):
|
||||
suite.FailNow("", "timeout waiting for suite.fromFederator")
|
||||
}
|
||||
msg, _ = suite.getFederatorMsg(5 * time.Second)
|
||||
suite.Equal(ap.ObjectProfile, msg.APObjectType)
|
||||
suite.Equal(ap.ActivityMove, msg.APActivityType)
|
||||
|
||||
|
@ -126,12 +114,7 @@ func (suite *MoveTestSuite) TestMove() {
|
|||
|
||||
// Should be a message heading to the processor
|
||||
// since this is just a retry with a different ID.
|
||||
select {
|
||||
case msg = <-suite.fromFederator:
|
||||
// Fine.
|
||||
case <-time.After(5 * time.Second):
|
||||
suite.FailNow("", "timeout waiting for suite.fromFederator")
|
||||
}
|
||||
msg, _ = suite.getFederatorMsg(5 * time.Second)
|
||||
suite.Equal(ap.ObjectProfile, msg.APObjectType)
|
||||
suite.Equal(ap.ActivityMove, msg.APActivityType)
|
||||
}
|
||||
|
|
|
@ -81,7 +81,8 @@ func (suite *RejectTestSuite) TestRejectFollowRequest() {
|
|||
suite.NoError(err)
|
||||
|
||||
// there should be nothing in the federator channel since nothing needs to be passed
|
||||
suite.Empty(suite.fromFederator)
|
||||
_, ok := suite.getFederatorMsg(time.Second)
|
||||
suite.False(ok)
|
||||
|
||||
// the follow request should not be in the database anymore -- it's been rejected
|
||||
err = suite.db.GetByID(ctx, fr.ID, >smodel.FollowRequest{})
|
||||
|
|
|
@ -98,13 +98,13 @@ func (f *federatingDB) updateAccountable(ctx context.Context, receivingAcct *gts
|
|||
// was delivered along with the Update, for further asynchronous
|
||||
// updating of eg., avatar/header, emojis, etc. The actual db
|
||||
// inserts/updates will take place there.
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityUpdate,
|
||||
GTSModel: requestingAcct,
|
||||
APObjectModel: accountable,
|
||||
ReceivingAccount: receivingAcct,
|
||||
RequestingAccount: requestingAcct,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityUpdate,
|
||||
GTSModel: requestingAcct,
|
||||
APObject: accountable,
|
||||
Receiving: receivingAcct,
|
||||
Requesting: requestingAcct,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
@ -155,13 +155,13 @@ func (f *federatingDB) updateStatusable(ctx context.Context, receivingAcct *gtsm
|
|||
|
||||
// Queue an UPDATE NOTE activity to our fedi API worker,
|
||||
// this will handle necessary database insertions, etc.
|
||||
f.state.Workers.EnqueueFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityUpdate,
|
||||
GTSModel: status, // original status
|
||||
APObjectModel: (ap.Statusable)(statusable),
|
||||
ReceivingAccount: receivingAcct,
|
||||
RequestingAccount: requestingAcct,
|
||||
f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityUpdate,
|
||||
GTSModel: status, // original status
|
||||
APObject: (ap.Statusable)(statusable),
|
||||
Receiving: receivingAcct,
|
||||
Requesting: requestingAcct,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
|
|
@ -59,9 +59,27 @@ var (
|
|||
// configuration values passed to initialized http.Transport{}
|
||||
// and http.Client{}, along with httpclient.Client{} specific.
|
||||
type Config struct {
|
||||
// MaxOpenConnsPerHost limits the max number of open connections to a host.
|
||||
|
||||
// MaxOpenConnsPerHost limits the max
|
||||
// number of open connections to a host.
|
||||
MaxOpenConnsPerHost int
|
||||
|
||||
// AllowRanges allows outgoing
|
||||
// communications to given IP nets.
|
||||
AllowRanges []netip.Prefix
|
||||
|
||||
// BlockRanges blocks outgoing
|
||||
// communiciations to given IP nets.
|
||||
BlockRanges []netip.Prefix
|
||||
|
||||
// TLSInsecureSkipVerify can be set to true to
|
||||
// skip validation of remote TLS certificates.
|
||||
//
|
||||
// THIS SHOULD BE USED FOR TESTING ONLY, IF YOU
|
||||
// TURN THIS ON WHILE RUNNING IN PRODUCTION YOU
|
||||
// ARE LEAVING YOUR SERVER WIDE OPEN TO ATTACKS!
|
||||
TLSInsecureSkipVerify bool
|
||||
|
||||
// MaxIdleConns: see http.Transport{}.MaxIdleConns.
|
||||
MaxIdleConns int
|
||||
|
||||
|
@ -79,20 +97,6 @@ type Config struct {
|
|||
|
||||
// DisableCompression: see http.Transport{}.DisableCompression.
|
||||
DisableCompression bool
|
||||
|
||||
// AllowRanges allows outgoing communications to given IP nets.
|
||||
AllowRanges []netip.Prefix
|
||||
|
||||
// BlockRanges blocks outgoing communiciations to given IP nets.
|
||||
BlockRanges []netip.Prefix
|
||||
|
||||
// TLSInsecureSkipVerify can be set to true to
|
||||
// skip validation of remote TLS certificates.
|
||||
//
|
||||
// THIS SHOULD BE USED FOR TESTING ONLY, IF YOU
|
||||
// TURN THIS ON WHILE RUNNING IN PRODUCTION YOU
|
||||
// ARE LEAVING YOUR SERVER WIDE OPEN TO ATTACKS!
|
||||
TLSInsecureSkipVerify bool
|
||||
}
|
||||
|
||||
// Client wraps an underlying http.Client{} to provide the following:
|
||||
|
@ -138,7 +142,8 @@ func New(cfg Config) *Client {
|
|||
cfg.MaxBodySize = int64(40 * bytesize.MiB)
|
||||
}
|
||||
|
||||
// Protect dialer with IP range sanitizer.
|
||||
// Protect the dialer
|
||||
// with IP range sanitizer.
|
||||
d.Control = (&Sanitizer{
|
||||
Allow: cfg.AllowRanges,
|
||||
Block: cfg.BlockRanges,
|
||||
|
@ -148,7 +153,7 @@ func New(cfg Config) *Client {
|
|||
c.client.Timeout = cfg.Timeout
|
||||
c.bodyMax = cfg.MaxBodySize
|
||||
|
||||
// Prepare TLS config for transport.
|
||||
// Prepare transport TLS config.
|
||||
tlsClientConfig := &tls.Config{
|
||||
InsecureSkipVerify: cfg.TLSInsecureSkipVerify, //nolint:gosec
|
||||
}
|
||||
|
|
|
@ -432,8 +432,8 @@ func (m *Manager) ProcessEmoji(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Attempt to add this emoji processing item to the worker queue.
|
||||
_ = m.state.Workers.Media.MustEnqueueCtx(ctx, emoji.Process)
|
||||
// Attempt to add emoji item to the worker queue.
|
||||
m.state.Workers.Media.Queue.Push(emoji.Process)
|
||||
|
||||
return emoji, nil
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ func (p *ProcessingEmoji) LoadEmoji(ctx context.Context) (*gtsmodel.Emoji, error
|
|||
// Provided context was cancelled, e.g. request cancelled
|
||||
// early. Queue this item for asynchronous processing.
|
||||
log.Warnf(ctx, "reprocessing emoji %s after canceled ctx", p.emoji.ID)
|
||||
go p.mgr.state.Workers.Media.Enqueue(p.Process)
|
||||
p.mgr.state.Workers.Media.Queue.Push(p.Process)
|
||||
}
|
||||
|
||||
return nil, err
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
|
||||
errorsv2 "codeberg.org/gruf/go-errors/v2"
|
||||
"codeberg.org/gruf/go-runners"
|
||||
"codeberg.org/superseriousbusiness/exif-terminator"
|
||||
terminator "codeberg.org/superseriousbusiness/exif-terminator"
|
||||
"github.com/disintegration/imaging"
|
||||
"github.com/h2non/filetype"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
|
@ -82,7 +82,7 @@ func (p *ProcessingMedia) LoadAttachment(ctx context.Context) (*gtsmodel.MediaAt
|
|||
// asynchronous processing, which will
|
||||
// use a background context.
|
||||
log.Warnf(ctx, "reprocessing media %s after canceled ctx", p.media.ID)
|
||||
go p.mgr.state.Workers.Media.Enqueue(p.Process)
|
||||
p.mgr.state.Workers.Media.Queue.Push(p.Process)
|
||||
}
|
||||
|
||||
// Media could not be retrieved FULLY,
|
||||
|
|
|
@ -20,25 +20,84 @@ package messages
|
|||
import (
|
||||
"net/url"
|
||||
|
||||
"codeberg.org/gruf/go-structr"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
// FromClientAPI wraps a message that travels from the client API into the processor.
|
||||
// FromClientAPI wraps a message that
|
||||
// travels from the client API into the processor.
|
||||
type FromClientAPI struct {
|
||||
APObjectType string
|
||||
|
||||
// APObjectType ...
|
||||
APObjectType string
|
||||
|
||||
// APActivityType ...
|
||||
APActivityType string
|
||||
GTSModel interface{}
|
||||
OriginAccount *gtsmodel.Account
|
||||
TargetAccount *gtsmodel.Account
|
||||
|
||||
// Optional GTS database model
|
||||
// of the Activity / Object.
|
||||
GTSModel interface{}
|
||||
|
||||
// Targeted object URI.
|
||||
TargetURI string
|
||||
|
||||
// Origin is the account that
|
||||
// this message originated from.
|
||||
Origin *gtsmodel.Account
|
||||
|
||||
// Target is the account that
|
||||
// this message is targeting.
|
||||
Target *gtsmodel.Account
|
||||
}
|
||||
|
||||
// FromFediAPI wraps a message that travels from the federating API into the processor.
|
||||
type FromFediAPI struct {
|
||||
APObjectType string
|
||||
APActivityType string
|
||||
APIri *url.URL
|
||||
APObjectModel interface{} // Optional AP model of the Object of the Activity. Should be Accountable or Statusable.
|
||||
GTSModel interface{} // Optional GTS model of the Activity or Object.
|
||||
RequestingAccount *gtsmodel.Account // Remote account that posted this Activity to the inbox.
|
||||
ReceivingAccount *gtsmodel.Account // Local account which owns the inbox that this Activity was posted to.
|
||||
// ClientMsgIndices defines queue indices this
|
||||
// message type should be accessible / stored under.
|
||||
func ClientMsgIndices() []structr.IndexConfig {
|
||||
return []structr.IndexConfig{
|
||||
{Fields: "TargetURI", Multiple: true},
|
||||
{Fields: "Origin.ID", Multiple: true},
|
||||
{Fields: "Target.ID", Multiple: true},
|
||||
}
|
||||
}
|
||||
|
||||
// FromFediAPI wraps a message that
|
||||
// travels from the federating API into the processor.
|
||||
type FromFediAPI struct {
|
||||
|
||||
// APObjectType ...
|
||||
APObjectType string
|
||||
|
||||
// APActivityType ...
|
||||
APActivityType string
|
||||
|
||||
// Optional ActivityPub ID (IRI)
|
||||
// and / or model of Activity / Object.
|
||||
APIRI *url.URL
|
||||
APObject interface{}
|
||||
|
||||
// Optional GTS database model
|
||||
// of the Activity / Object.
|
||||
GTSModel interface{}
|
||||
|
||||
// Targeted object URI.
|
||||
TargetURI string
|
||||
|
||||
// Remote account that posted
|
||||
// this Activity to the inbox.
|
||||
Requesting *gtsmodel.Account
|
||||
|
||||
// Local account which owns the inbox
|
||||
// that this Activity was posted to.
|
||||
Receiving *gtsmodel.Account
|
||||
}
|
||||
|
||||
// FederatorMsgIndices defines queue indices this
|
||||
// message type should be accessible / stored under.
|
||||
func FederatorMsgIndices() []structr.IndexConfig {
|
||||
return []structr.IndexConfig{
|
||||
{Fields: "APIRI", Multiple: true},
|
||||
{Fields: "TargetURI", Multiple: true},
|
||||
{Fields: "Requesting.ID", Multiple: true},
|
||||
{Fields: "Receiving.ID", Multiple: true},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
// GoToSocial
|
||||
// Copyright (C) GoToSocial Authors admin@gotosocial.org
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package oauth
|
||||
|
||||
import (
|
||||
|
|
|
@ -19,6 +19,7 @@ package account_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
|
@ -48,7 +49,6 @@ type AccountStandardTestSuite struct {
|
|||
state state.State
|
||||
mediaManager *media.Manager
|
||||
oauthServer oauth.Server
|
||||
fromClientAPIChan chan messages.FromClientAPI
|
||||
transportController transport.Controller
|
||||
federator *federation.Federator
|
||||
emailSender email.Sender
|
||||
|
@ -68,6 +68,13 @@ type AccountStandardTestSuite struct {
|
|||
accountProcessor account.Processor
|
||||
}
|
||||
|
||||
func (suite *AccountStandardTestSuite) getClientMsg(timeout time.Duration) (*messages.FromClientAPI, bool) {
|
||||
ctx := context.Background()
|
||||
ctx, cncl := context.WithTimeout(ctx, timeout)
|
||||
defer cncl()
|
||||
return suite.state.Workers.Client.Queue.PopCtx(ctx)
|
||||
}
|
||||
|
||||
func (suite *AccountStandardTestSuite) SetupSuite() {
|
||||
suite.testTokens = testrig.NewTestTokens()
|
||||
suite.testClients = testrig.NewTestClients()
|
||||
|
@ -101,13 +108,6 @@ func (suite *AccountStandardTestSuite) SetupTest() {
|
|||
suite.mediaManager = testrig.NewTestMediaManager(&suite.state)
|
||||
suite.oauthServer = testrig.NewTestOauthServer(suite.db)
|
||||
|
||||
suite.fromClientAPIChan = make(chan messages.FromClientAPI, 100)
|
||||
suite.state.Workers.EnqueueClientAPI = func(ctx context.Context, msgs ...messages.FromClientAPI) {
|
||||
for _, msg := range msgs {
|
||||
suite.fromClientAPIChan <- msg
|
||||
}
|
||||
}
|
||||
|
||||
suite.transportController = testrig.NewTestTransportController(&suite.state, testrig.NewMockHTTPClient(nil, "../../../testrig/media"))
|
||||
suite.federator = testrig.NewTestFederator(&suite.state, suite.transportController, suite.mediaManager)
|
||||
suite.sentEmails = make(map[string]string)
|
||||
|
|
|
@ -83,16 +83,16 @@ func (p *Processor) BlockCreate(ctx context.Context, requestingAccount *gtsmodel
|
|||
}
|
||||
|
||||
// Process block side effects (federation etc).
|
||||
msgs = append(msgs, messages.FromClientAPI{
|
||||
msgs = append(msgs, &messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityBlock,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: block,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetAccount,
|
||||
Origin: requestingAccount,
|
||||
Target: targetAccount,
|
||||
})
|
||||
|
||||
// Batch queue accreted client api messages.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, msgs...)
|
||||
p.state.Workers.Client.Queue.Push(msgs...)
|
||||
|
||||
return p.RelationshipGet(ctx, requestingAccount, targetAccountID)
|
||||
}
|
||||
|
@ -120,12 +120,12 @@ func (p *Processor) BlockRemove(ctx context.Context, requestingAccount *gtsmodel
|
|||
existingBlock.TargetAccount = targetAccount
|
||||
|
||||
// Process block removal side effects (federation etc).
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityBlock,
|
||||
APActivityType: ap.ActivityUndo,
|
||||
GTSModel: existingBlock,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetAccount,
|
||||
Origin: requestingAccount,
|
||||
Target: targetAccount,
|
||||
})
|
||||
|
||||
return p.RelationshipGet(ctx, requestingAccount, targetAccountID)
|
||||
|
|
|
@ -126,11 +126,11 @@ func (p *Processor) Create(
|
|||
|
||||
// There are side effects for creating a new account
|
||||
// (confirmation emails etc), perform these async.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: user,
|
||||
OriginAccount: user.Account,
|
||||
Origin: user.Account,
|
||||
})
|
||||
|
||||
return user, nil
|
||||
|
|
|
@ -102,16 +102,13 @@ func (p *Processor) Delete(
|
|||
// and the above Delete function will be called afterwards from the processor, to clear
|
||||
// out the account's bits and bobs, and stubbify it.
|
||||
func (p *Processor) DeleteSelf(ctx context.Context, account *gtsmodel.Account) gtserror.WithCode {
|
||||
fromClientAPIMessage := messages.FromClientAPI{
|
||||
// Process the delete side effects asynchronously.
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActorPerson,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
OriginAccount: account,
|
||||
TargetAccount: account,
|
||||
}
|
||||
|
||||
// Process the delete side effects asynchronously.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, fromClientAPIMessage)
|
||||
|
||||
Origin: account,
|
||||
Target: account,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -193,7 +190,8 @@ func (p *Processor) deleteAccountFollows(ctx context.Context, account *gtsmodel.
|
|||
|
||||
var (
|
||||
// Use this slice to batch unfollow messages.
|
||||
msgs = []messages.FromClientAPI{}
|
||||
msgs = []*messages.FromClientAPI{}
|
||||
|
||||
// To avoid checking if account is local over + over
|
||||
// inside the subsequent loops, just generate static
|
||||
// side effects function once now.
|
||||
|
@ -214,7 +212,7 @@ func (p *Processor) deleteAccountFollows(ctx context.Context, account *gtsmodel.
|
|||
}
|
||||
if msg := unfollowSideEffects(ctx, account, follow); msg != nil {
|
||||
// There was a side effect to process.
|
||||
msgs = append(msgs, *msg)
|
||||
msgs = append(msgs, msg)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,13 +242,13 @@ func (p *Processor) deleteAccountFollows(ctx context.Context, account *gtsmodel.
|
|||
|
||||
if msg := unfollowSideEffects(ctx, account, follow); msg != nil {
|
||||
// There was a side effect to process.
|
||||
msgs = append(msgs, *msg)
|
||||
msgs = append(msgs, msg)
|
||||
}
|
||||
}
|
||||
|
||||
// Process accreted messages in serial.
|
||||
for _, msg := range msgs {
|
||||
if err := p.state.Workers.ProcessFromClientAPI(ctx, msg); err != nil {
|
||||
if err := p.state.Workers.Client.Process(ctx, msg); err != nil {
|
||||
log.Errorf(
|
||||
ctx,
|
||||
"error processing %s of %s during Delete of account %s: %v",
|
||||
|
@ -306,8 +304,8 @@ func (p *Processor) unfollowSideEffectsFunc(local bool) func(
|
|||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityUndo,
|
||||
GTSModel: follow,
|
||||
OriginAccount: account,
|
||||
TargetAccount: follow.TargetAccount,
|
||||
Origin: account,
|
||||
Target: follow.TargetAccount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -337,7 +335,7 @@ func (p *Processor) deleteAccountStatuses(
|
|||
statuses []*gtsmodel.Status
|
||||
err error
|
||||
maxID string
|
||||
msgs = []messages.FromClientAPI{}
|
||||
msgs = []*messages.FromClientAPI{}
|
||||
)
|
||||
|
||||
statusLoop:
|
||||
|
@ -404,29 +402,29 @@ statusLoop:
|
|||
continue
|
||||
}
|
||||
|
||||
msgs = append(msgs, messages.FromClientAPI{
|
||||
msgs = append(msgs, &messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityUndo,
|
||||
GTSModel: status,
|
||||
OriginAccount: boost.Account,
|
||||
TargetAccount: account,
|
||||
Origin: boost.Account,
|
||||
Target: account,
|
||||
})
|
||||
}
|
||||
|
||||
// Now prepare to Delete status.
|
||||
msgs = append(msgs, messages.FromClientAPI{
|
||||
msgs = append(msgs, &messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: status,
|
||||
OriginAccount: account,
|
||||
TargetAccount: account,
|
||||
Origin: account,
|
||||
Target: account,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Process accreted messages in serial.
|
||||
for _, msg := range msgs {
|
||||
if err := p.state.Workers.ProcessFromClientAPI(ctx, msg); err != nil {
|
||||
if err := p.state.Workers.Client.Process(ctx, msg); err != nil {
|
||||
log.Errorf(
|
||||
ctx,
|
||||
"error processing %s of %s during Delete of account %s: %v",
|
||||
|
|
|
@ -117,12 +117,12 @@ func (p *Processor) FollowCreate(ctx context.Context, requestingAccount *gtsmode
|
|||
} else {
|
||||
// Otherwise we leave the follow request as it is,
|
||||
// and we handle the rest of the process async.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: fr,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetAccount,
|
||||
Origin: requestingAccount,
|
||||
Target: targetAccount,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ func (p *Processor) FollowRemove(ctx context.Context, requestingAccount *gtsmode
|
|||
}
|
||||
|
||||
// Batch queue accreted client api messages.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, msgs...)
|
||||
p.state.Workers.Client.Queue.Push(msgs...)
|
||||
|
||||
return p.RelationshipGet(ctx, requestingAccount, targetAccountID)
|
||||
}
|
||||
|
@ -225,8 +225,8 @@ func (p *Processor) getFollowTarget(ctx context.Context, requester *gtsmodel.Acc
|
|||
// If a follow and/or follow request was removed this way, one or two
|
||||
// messages will be returned which should then be processed by a client
|
||||
// api worker.
|
||||
func (p *Processor) unfollow(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) ([]messages.FromClientAPI, error) {
|
||||
var msgs []messages.FromClientAPI
|
||||
func (p *Processor) unfollow(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) ([]*messages.FromClientAPI, error) {
|
||||
var msgs []*messages.FromClientAPI
|
||||
|
||||
// Get follow from requesting account to target account.
|
||||
follow, err := p.state.DB.GetFollow(ctx, requestingAccount.ID, targetAccount.ID)
|
||||
|
@ -251,7 +251,7 @@ func (p *Processor) unfollow(ctx context.Context, requestingAccount *gtsmodel.Ac
|
|||
}
|
||||
|
||||
// Follow status changed, process side effects.
|
||||
msgs = append(msgs, messages.FromClientAPI{
|
||||
msgs = append(msgs, &messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityUndo,
|
||||
GTSModel: >smodel.Follow{
|
||||
|
@ -259,8 +259,8 @@ func (p *Processor) unfollow(ctx context.Context, requestingAccount *gtsmodel.Ac
|
|||
TargetAccountID: targetAccount.ID,
|
||||
URI: follow.URI,
|
||||
},
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetAccount,
|
||||
Origin: requestingAccount,
|
||||
Target: targetAccount,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -287,7 +287,7 @@ func (p *Processor) unfollow(ctx context.Context, requestingAccount *gtsmodel.Ac
|
|||
}
|
||||
|
||||
// Follow status changed, process side effects.
|
||||
msgs = append(msgs, messages.FromClientAPI{
|
||||
msgs = append(msgs, &messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityUndo,
|
||||
GTSModel: >smodel.Follow{
|
||||
|
@ -295,8 +295,8 @@ func (p *Processor) unfollow(ctx context.Context, requestingAccount *gtsmodel.Ac
|
|||
TargetAccountID: targetAccount.ID,
|
||||
URI: followReq.URI,
|
||||
},
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetAccount,
|
||||
Origin: requestingAccount,
|
||||
Target: targetAccount,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -40,12 +40,12 @@ func (p *Processor) FollowRequestAccept(ctx context.Context, requestingAccount *
|
|||
if follow.Account != nil {
|
||||
// Only enqueue work in the case we have a request creating account stored.
|
||||
// NOTE: due to how AcceptFollowRequest works, the inverse shouldn't be possible.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityAccept,
|
||||
GTSModel: follow,
|
||||
OriginAccount: follow.Account,
|
||||
TargetAccount: follow.TargetAccount,
|
||||
Origin: follow.Account,
|
||||
Target: follow.TargetAccount,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -67,12 +67,12 @@ func (p *Processor) FollowRequestReject(ctx context.Context, requestingAccount *
|
|||
if followRequest.Account != nil {
|
||||
// Only enqueue work in the case we have a request creating account stored.
|
||||
// NOTE: due to how GetFollowRequest works, the inverse shouldn't be possible.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityReject,
|
||||
GTSModel: followRequest,
|
||||
OriginAccount: followRequest.Account,
|
||||
TargetAccount: followRequest.TargetAccount,
|
||||
Origin: followRequest.Account,
|
||||
Target: followRequest.TargetAccount,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import (
|
|||
"github.com/stretchr/testify/suite"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
|
@ -152,18 +151,11 @@ func (suite *FollowTestSuite) TestFollowRequestLocal() {
|
|||
}
|
||||
|
||||
// There should be a message going to the worker.
|
||||
var cMsg messages.FromClientAPI
|
||||
select {
|
||||
case cMsg = <-suite.fromClientAPIChan:
|
||||
// No problem.
|
||||
case <-time.After(5 * time.Second):
|
||||
suite.FailNow("timed out waiting for message")
|
||||
}
|
||||
|
||||
cMsg, _ := suite.getClientMsg(5 * time.Second)
|
||||
suite.Equal(ap.ActivityCreate, cMsg.APActivityType)
|
||||
suite.Equal(ap.ActivityFollow, cMsg.APObjectType)
|
||||
suite.Equal(requestingAccount.ID, cMsg.OriginAccount.ID)
|
||||
suite.Equal(targetAccount.ID, cMsg.TargetAccount.ID)
|
||||
suite.Equal(requestingAccount.ID, cMsg.Origin.ID)
|
||||
suite.Equal(targetAccount.ID, cMsg.Target.ID)
|
||||
}
|
||||
|
||||
func TestFollowTestS(t *testing.T) {
|
||||
|
|
|
@ -317,12 +317,12 @@ func (p *Processor) MoveSelf(
|
|||
}
|
||||
|
||||
// Everything seems OK, process Move side effects async.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActorPerson,
|
||||
APActivityType: ap.ActivityMove,
|
||||
GTSModel: move,
|
||||
OriginAccount: originAcct,
|
||||
TargetAccount: targetAcct,
|
||||
Origin: originAcct,
|
||||
Target: targetAcct,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
|
|
@ -70,29 +70,23 @@ func (suite *MoveTestSuite) TestMoveAccountOK() {
|
|||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
||||
// There should be a msg heading back to fromClientAPI.
|
||||
select {
|
||||
case msg := <-suite.fromClientAPIChan:
|
||||
move, ok := msg.GTSModel.(*gtsmodel.Move)
|
||||
if !ok {
|
||||
suite.FailNow("", "could not cast %T to *gtsmodel.Move", move)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
suite.WithinDuration(now, move.CreatedAt, 5*time.Second)
|
||||
suite.WithinDuration(now, move.UpdatedAt, 5*time.Second)
|
||||
suite.WithinDuration(now, move.AttemptedAt, 5*time.Second)
|
||||
suite.Zero(move.SucceededAt)
|
||||
suite.NotZero(move.ID)
|
||||
suite.Equal(requestingAcct.URI, move.OriginURI)
|
||||
suite.NotNil(move.Origin)
|
||||
suite.Equal(targetAcct.URI, move.TargetURI)
|
||||
suite.NotNil(move.Target)
|
||||
suite.NotZero(move.URI)
|
||||
|
||||
case <-time.After(5 * time.Second):
|
||||
suite.FailNow("time out waiting for message")
|
||||
// There should be a message going to the worker.
|
||||
cMsg, _ := suite.getClientMsg(5 * time.Second)
|
||||
move, ok := cMsg.GTSModel.(*gtsmodel.Move)
|
||||
if !ok {
|
||||
suite.FailNow("", "could not cast %T to *gtsmodel.Move", move)
|
||||
}
|
||||
now := time.Now()
|
||||
suite.WithinDuration(now, move.CreatedAt, 5*time.Second)
|
||||
suite.WithinDuration(now, move.UpdatedAt, 5*time.Second)
|
||||
suite.WithinDuration(now, move.AttemptedAt, 5*time.Second)
|
||||
suite.Zero(move.SucceededAt)
|
||||
suite.NotZero(move.ID)
|
||||
suite.Equal(requestingAcct.URI, move.OriginURI)
|
||||
suite.NotNil(move.Origin)
|
||||
suite.Equal(targetAcct.URI, move.TargetURI)
|
||||
suite.NotNil(move.Target)
|
||||
suite.NotZero(move.URI)
|
||||
|
||||
// Move should be in the database now.
|
||||
move, err := suite.state.DB.GetMoveByOriginTarget(
|
||||
|
|
|
@ -296,11 +296,11 @@ func (p *Processor) Update(ctx context.Context, account *gtsmodel.Account, form
|
|||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("could not update account settings %s: %s", account.ID, err))
|
||||
}
|
||||
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityUpdate,
|
||||
GTSModel: account,
|
||||
OriginAccount: account,
|
||||
Origin: account,
|
||||
})
|
||||
|
||||
acctSensitive, err := p.converter.AccountToAPIAccountSensitive(ctx, account)
|
||||
|
|
|
@ -20,6 +20,7 @@ package account_test
|
|||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
|
@ -31,20 +32,6 @@ type AccountUpdateTestSuite struct {
|
|||
AccountStandardTestSuite
|
||||
}
|
||||
|
||||
func (suite *AccountStandardTestSuite) checkClientAPIChan(accountID string) {
|
||||
msg := <-suite.fromClientAPIChan
|
||||
|
||||
// Profile update.
|
||||
suite.Equal(ap.ActivityUpdate, msg.APActivityType)
|
||||
suite.Equal(ap.ObjectProfile, msg.APObjectType)
|
||||
|
||||
// Correct account updated.
|
||||
if msg.OriginAccount == nil {
|
||||
suite.FailNow("expected msg.OriginAccount not to be nil")
|
||||
}
|
||||
suite.Equal(accountID, msg.OriginAccount.ID)
|
||||
}
|
||||
|
||||
func (suite *AccountUpdateTestSuite) TestAccountUpdateSimple() {
|
||||
testAccount := >smodel.Account{}
|
||||
*testAccount = *suite.testAccounts["local_account_1"]
|
||||
|
@ -73,7 +60,17 @@ func (suite *AccountUpdateTestSuite) TestAccountUpdateSimple() {
|
|||
suite.Equal(noteExpected, apiAccount.Note)
|
||||
|
||||
// We should have an update in the client api channel.
|
||||
suite.checkClientAPIChan(testAccount.ID)
|
||||
msg, _ := suite.getClientMsg(5 * time.Second)
|
||||
|
||||
// Profile update.
|
||||
suite.Equal(ap.ActivityUpdate, msg.APActivityType)
|
||||
suite.Equal(ap.ObjectProfile, msg.APObjectType)
|
||||
|
||||
// Correct account updated.
|
||||
if msg.Origin == nil {
|
||||
suite.FailNow("expected msg.OriginAccount not to be nil")
|
||||
}
|
||||
suite.Equal(testAccount.ID, msg.Origin.ID)
|
||||
|
||||
// Check database model of account as well.
|
||||
dbAccount, err := suite.db.GetAccountByID(ctx, testAccount.ID)
|
||||
|
@ -113,7 +110,17 @@ func (suite *AccountUpdateTestSuite) TestAccountUpdateWithMention() {
|
|||
suite.Equal(noteExpected, apiAccount.Note)
|
||||
|
||||
// We should have an update in the client api channel.
|
||||
suite.checkClientAPIChan(testAccount.ID)
|
||||
msg, _ := suite.getClientMsg(5 * time.Second)
|
||||
|
||||
// Profile update.
|
||||
suite.Equal(ap.ActivityUpdate, msg.APActivityType)
|
||||
suite.Equal(ap.ObjectProfile, msg.APObjectType)
|
||||
|
||||
// Correct account updated.
|
||||
if msg.Origin == nil {
|
||||
suite.FailNow("expected msg.OriginAccount not to be nil")
|
||||
}
|
||||
suite.Equal(testAccount.ID, msg.Origin.ID)
|
||||
|
||||
// Check database model of account as well.
|
||||
dbAccount, err := suite.db.GetAccountByID(ctx, testAccount.ID)
|
||||
|
@ -159,7 +166,17 @@ func (suite *AccountUpdateTestSuite) TestAccountUpdateWithMarkdownNote() {
|
|||
suite.Equal(noteExpected, apiAccount.Note)
|
||||
|
||||
// We should have an update in the client api channel.
|
||||
suite.checkClientAPIChan(testAccount.ID)
|
||||
msg, _ := suite.getClientMsg(5 * time.Second)
|
||||
|
||||
// Profile update.
|
||||
suite.Equal(ap.ActivityUpdate, msg.APActivityType)
|
||||
suite.Equal(ap.ObjectProfile, msg.APObjectType)
|
||||
|
||||
// Correct account updated.
|
||||
if msg.Origin == nil {
|
||||
suite.FailNow("expected msg.OriginAccount not to be nil")
|
||||
}
|
||||
suite.Equal(testAccount.ID, msg.Origin.ID)
|
||||
|
||||
// Check database model of account as well.
|
||||
dbAccount, err := suite.db.GetAccountByID(ctx, testAccount.ID)
|
||||
|
@ -234,7 +251,17 @@ func (suite *AccountUpdateTestSuite) TestAccountUpdateWithFields() {
|
|||
suite.EqualValues(emojisExpected, apiAccount.Emojis)
|
||||
|
||||
// We should have an update in the client api channel.
|
||||
suite.checkClientAPIChan(testAccount.ID)
|
||||
msg, _ := suite.getClientMsg(5 * time.Second)
|
||||
|
||||
// Profile update.
|
||||
suite.Equal(ap.ActivityUpdate, msg.APActivityType)
|
||||
suite.Equal(ap.ObjectProfile, msg.APObjectType)
|
||||
|
||||
// Correct account updated.
|
||||
if msg.Origin == nil {
|
||||
suite.FailNow("expected msg.OriginAccount not to be nil")
|
||||
}
|
||||
suite.Equal(testAccount.ID, msg.Origin.ID)
|
||||
|
||||
// Check database model of account as well.
|
||||
dbAccount, err := suite.db.GetAccountByID(ctx, testAccount.ID)
|
||||
|
@ -281,7 +308,17 @@ func (suite *AccountUpdateTestSuite) TestAccountUpdateNoteNotFields() {
|
|||
suite.Equal(fieldsBefore, len(apiAccount.Fields))
|
||||
|
||||
// We should have an update in the client api channel.
|
||||
suite.checkClientAPIChan(testAccount.ID)
|
||||
msg, _ := suite.getClientMsg(5 * time.Second)
|
||||
|
||||
// Profile update.
|
||||
suite.Equal(ap.ActivityUpdate, msg.APActivityType)
|
||||
suite.Equal(ap.ObjectProfile, msg.APObjectType)
|
||||
|
||||
// Correct account updated.
|
||||
if msg.Origin == nil {
|
||||
suite.FailNow("expected msg.OriginAccount not to be nil")
|
||||
}
|
||||
suite.Equal(testAccount.ID, msg.Origin.ID)
|
||||
|
||||
// Check database model of account as well.
|
||||
dbAccount, err := suite.db.GetAccountByID(ctx, testAccount.ID)
|
||||
|
|
|
@ -80,13 +80,13 @@ func (p *Processor) accountActionSuspend(
|
|||
Text: text,
|
||||
},
|
||||
func(ctx context.Context) gtserror.MultiError {
|
||||
if err := p.state.Workers.ProcessFromClientAPI(
|
||||
if err := p.state.Workers.Client.Process(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ActorPerson,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
OriginAccount: adminAcct,
|
||||
TargetAccount: targetAcct,
|
||||
Origin: adminAcct,
|
||||
Target: targetAcct,
|
||||
},
|
||||
); err != nil {
|
||||
errs := gtserror.NewMultiError(1)
|
||||
|
|
|
@ -54,12 +54,12 @@ func (p *Processor) AccountApprove(
|
|||
|
||||
if !*user.Approved {
|
||||
// Process approval side effects asynschronously.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActorPerson,
|
||||
APActivityType: ap.ActivityAccept,
|
||||
GTSModel: user,
|
||||
OriginAccount: adminAcct,
|
||||
TargetAccount: user.Account,
|
||||
Origin: adminAcct,
|
||||
Target: user.Account,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -101,12 +101,12 @@ func (p *Processor) AccountReject(
|
|||
}
|
||||
|
||||
// Process rejection side effects asynschronously.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActorPerson,
|
||||
APActivityType: ap.ActivityReject,
|
||||
GTSModel: deniedUser,
|
||||
OriginAccount: adminAcct,
|
||||
TargetAccount: user.Account,
|
||||
Origin: adminAcct,
|
||||
Target: user.Account,
|
||||
})
|
||||
|
||||
return apiAccount, nil
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
|
@ -97,8 +98,10 @@ func (a *Actions) Run(
|
|||
// we're done modifying it for now.
|
||||
a.m.Unlock()
|
||||
|
||||
// Do the rest of the work asynchronously.
|
||||
a.state.Workers.ClientAPI.Enqueue(func(ctx context.Context) {
|
||||
go func() {
|
||||
// Use a background context with existing values.
|
||||
ctx = gtscontext.WithValues(context.Background(), ctx)
|
||||
|
||||
// Run the thing and collect errors.
|
||||
if errs := f(ctx); errs != nil {
|
||||
action.Errors = make([]string, 0, len(errs))
|
||||
|
@ -119,7 +122,7 @@ func (a *Actions) Run(
|
|||
if err := a.state.DB.UpdateAdminAction(ctx, action, "completed_at", "errors"); err != nil {
|
||||
log.Errorf(ctx, "db error marking action %s as completed: %q", actionKey, err)
|
||||
}
|
||||
})
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -201,15 +201,13 @@ func (p *Processor) domainBlockSideEffects(
|
|||
// process an account delete message to remove
|
||||
// that account's posts, media, etc.
|
||||
if err := p.rangeDomainAccounts(ctx, block.Domain, func(account *gtsmodel.Account) {
|
||||
cMsg := messages.FromClientAPI{
|
||||
if err := p.state.Workers.Client.Process(ctx, &messages.FromClientAPI{
|
||||
APObjectType: ap.ActorPerson,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: block,
|
||||
OriginAccount: account,
|
||||
TargetAccount: account,
|
||||
}
|
||||
|
||||
if err := p.state.Workers.ProcessFromClientAPI(ctx, cMsg); err != nil {
|
||||
Origin: account,
|
||||
Target: account,
|
||||
}); err != nil {
|
||||
errs.Append(err)
|
||||
}
|
||||
}); err != nil {
|
||||
|
|
|
@ -140,12 +140,12 @@ func (p *Processor) ReportResolve(ctx context.Context, account *gtsmodel.Account
|
|||
}
|
||||
|
||||
// Process side effects of closing the report.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityFlag,
|
||||
APActivityType: ap.ActivityUpdate,
|
||||
GTSModel: report,
|
||||
OriginAccount: account,
|
||||
TargetAccount: report.Account,
|
||||
Origin: account,
|
||||
Target: report.Account,
|
||||
})
|
||||
|
||||
apimodelReport, err := p.converter.ReportToAdminAPIReport(ctx, updatedReport, account)
|
||||
|
|
|
@ -116,11 +116,11 @@ func (p *Processor) onExpiry(pollID string) func(context.Context, time.Time) {
|
|||
|
||||
// Enqueue a status update operation to the client API worker,
|
||||
// this will asynchronously send an update with the Poll close time.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APActivityType: ap.ActivityUpdate,
|
||||
APObjectType: ap.ObjectNote,
|
||||
GTSModel: status,
|
||||
OriginAccount: status.Account,
|
||||
Origin: status.Account,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,11 +96,11 @@ func (p *Processor) PollVote(ctx context.Context, requester *gtsmodel.Account, p
|
|||
poll.IncrementVotes(choices)
|
||||
|
||||
// Enqueue worker task to handle side-effects of user poll vote(s).
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APActivityType: ap.ActivityCreate,
|
||||
APObjectType: ap.ActivityQuestion,
|
||||
GTSModel: vote, // the vote choices
|
||||
OriginAccount: requester,
|
||||
Origin: requester,
|
||||
})
|
||||
|
||||
// Return converted API model poll.
|
||||
|
|
|
@ -95,7 +95,6 @@ func (suite *ProcessingStandardTestSuite) SetupSuite() {
|
|||
|
||||
func (suite *ProcessingStandardTestSuite) SetupTest() {
|
||||
suite.state.Caches.Init()
|
||||
testrig.StartNoopWorkers(&suite.state)
|
||||
|
||||
testrig.InitTestConfig()
|
||||
testrig.InitTestLog()
|
||||
|
@ -124,8 +123,7 @@ func (suite *ProcessingStandardTestSuite) SetupTest() {
|
|||
suite.emailSender = testrig.NewEmailSender("../../web/template/", nil)
|
||||
|
||||
suite.processor = processing.NewProcessor(cleaner.New(&suite.state), suite.typeconverter, suite.federator, suite.oauthServer, suite.mediaManager, &suite.state, suite.emailSender)
|
||||
suite.state.Workers.EnqueueClientAPI = suite.processor.Workers().EnqueueClientAPI
|
||||
suite.state.Workers.EnqueueFediAPI = suite.processor.Workers().EnqueueFediAPI
|
||||
testrig.StartWorkers(&suite.state, suite.processor.Workers())
|
||||
|
||||
testrig.StandardDBSetup(suite.db, suite.testAccounts)
|
||||
testrig.StandardStorageSetup(suite.storage, "../../testrig/media")
|
||||
|
|
|
@ -91,12 +91,12 @@ func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form
|
|||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityFlag,
|
||||
GTSModel: report,
|
||||
OriginAccount: account,
|
||||
TargetAccount: targetAccount,
|
||||
Origin: account,
|
||||
Target: targetAccount,
|
||||
})
|
||||
|
||||
apiReport, err := p.converter.ReportToAPIReport(ctx, report)
|
||||
|
|
|
@ -89,12 +89,12 @@ func (p *Processor) BoostCreate(
|
|||
}
|
||||
|
||||
// Process side effects asynchronously.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: boost,
|
||||
OriginAccount: requester,
|
||||
TargetAccount: target.Account,
|
||||
Origin: requester,
|
||||
Target: target.Account,
|
||||
})
|
||||
|
||||
return p.c.GetAPIStatus(ctx, requester, boost)
|
||||
|
@ -141,12 +141,12 @@ func (p *Processor) BoostRemove(
|
|||
|
||||
if boost != nil {
|
||||
// Status was boosted. Process unboost side effects asynchronously.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityUndo,
|
||||
GTSModel: boost,
|
||||
OriginAccount: requester,
|
||||
TargetAccount: target.Account,
|
||||
Origin: requester,
|
||||
Target: target.Account,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -143,11 +143,11 @@ func (p *Processor) Create(
|
|||
}
|
||||
|
||||
// send it back to the client API worker for async side-effects.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
OriginAccount: requester,
|
||||
Origin: requester,
|
||||
})
|
||||
|
||||
if status.Poll != nil {
|
||||
|
|
|
@ -51,12 +51,12 @@ func (p *Processor) Delete(ctx context.Context, requestingAccount *gtsmodel.Acco
|
|||
}
|
||||
|
||||
// Process delete side effects.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: targetStatus,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: requestingAccount,
|
||||
Origin: requestingAccount,
|
||||
Target: requestingAccount,
|
||||
})
|
||||
|
||||
return apiStatus, nil
|
||||
|
|
|
@ -107,12 +107,12 @@ func (p *Processor) FaveCreate(ctx context.Context, requestingAccount *gtsmodel.
|
|||
}
|
||||
|
||||
// Process new status fave side effects.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityLike,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: gtsFave,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetStatus.Account,
|
||||
Origin: requestingAccount,
|
||||
Target: targetStatus.Account,
|
||||
})
|
||||
|
||||
return p.c.GetAPIStatus(ctx, requestingAccount, targetStatus)
|
||||
|
@ -137,12 +137,12 @@ func (p *Processor) FaveRemove(ctx context.Context, requestingAccount *gtsmodel.
|
|||
}
|
||||
|
||||
// Process remove status fave side effects.
|
||||
p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{
|
||||
p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityLike,
|
||||
APActivityType: ap.ActivityUndo,
|
||||
GTSModel: existingFave,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetStatus.Account,
|
||||
Origin: requestingAccount,
|
||||
Target: targetStatus.Account,
|
||||
})
|
||||
|
||||
return p.c.GetAPIStatus(ctx, requestingAccount, targetStatus)
|
||||
|
|
|
@ -75,12 +75,6 @@ func (f *federate) DeleteAccount(ctx context.Context, account *gtsmodel.Account)
|
|||
return nil
|
||||
}
|
||||
|
||||
// Drop any queued outgoing AP requests to / from account,
|
||||
// (this stops any queued likes, boosts, creates etc).
|
||||
f.state.Workers.Delivery.Queue.Delete("ActorID", account.URI)
|
||||
f.state.Workers.Delivery.Queue.Delete("ObjectID", account.URI)
|
||||
f.state.Workers.Delivery.Queue.Delete("TargetID", account.URI)
|
||||
|
||||
// Parse relevant URI(s).
|
||||
outboxIRI, err := parseURI(account.OutboxURI)
|
||||
if err != nil {
|
||||
|
@ -228,16 +222,6 @@ func (f *federate) DeleteStatus(ctx context.Context, status *gtsmodel.Status) er
|
|||
return nil
|
||||
}
|
||||
|
||||
// Drop any queued outgoing http requests for status,
|
||||
// (this stops any queued likes, boosts, creates etc).
|
||||
f.state.Workers.Delivery.Queue.Delete("ObjectID", status.URI)
|
||||
f.state.Workers.Delivery.Queue.Delete("TargetID", status.URI)
|
||||
|
||||
// Ensure the status model is fully populated.
|
||||
if err := f.state.DB.PopulateStatus(ctx, status); err != nil {
|
||||
return gtserror.Newf("error populating status: %w", err)
|
||||
}
|
||||
|
||||
// Parse the outbox URI of the status author.
|
||||
outboxIRI, err := parseURI(status.Account.OutboxURI)
|
||||
if err != nil {
|
||||
|
|
|
@ -25,7 +25,6 @@ import (
|
|||
"codeberg.org/gruf/go-logger/v2/level"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
|
@ -45,29 +44,15 @@ type clientAPI struct {
|
|||
surface *surface
|
||||
federate *federate
|
||||
account *account.Processor
|
||||
utilF *utilF
|
||||
utils *utils
|
||||
}
|
||||
|
||||
func (p *Processor) EnqueueClientAPI(cctx context.Context, msgs ...messages.FromClientAPI) {
|
||||
_ = p.workers.ClientAPI.MustEnqueueCtx(cctx, func(wctx context.Context) {
|
||||
// Copy caller ctx values to worker's.
|
||||
wctx = gtscontext.WithValues(wctx, cctx)
|
||||
|
||||
// Process worker messages.
|
||||
for _, msg := range msgs {
|
||||
if err := p.ProcessFromClientAPI(wctx, msg); err != nil {
|
||||
log.Errorf(wctx, "error processing client API message: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Processor) ProcessFromClientAPI(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *Processor) ProcessFromClientAPI(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
// Allocate new log fields slice
|
||||
fields := make([]kv.Field, 3, 4)
|
||||
fields[0] = kv.Field{"activityType", cMsg.APActivityType}
|
||||
fields[1] = kv.Field{"objectType", cMsg.APObjectType}
|
||||
fields[2] = kv.Field{"fromAccount", cMsg.OriginAccount.Username}
|
||||
fields[2] = kv.Field{"fromAccount", cMsg.Origin.Username}
|
||||
|
||||
// Include GTSModel in logs if appropriate.
|
||||
if cMsg.GTSModel != nil &&
|
||||
|
@ -217,7 +202,7 @@ func (p *Processor) ProcessFromClientAPI(ctx context.Context, cMsg messages.From
|
|||
return gtserror.Newf("unhandled: %s %s", cMsg.APActivityType, cMsg.APObjectType)
|
||||
}
|
||||
|
||||
func (p *clientAPI) CreateAccount(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) CreateAccount(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
newUser, ok := cMsg.GTSModel.(*gtsmodel.User)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.User", cMsg.GTSModel)
|
||||
|
@ -241,14 +226,14 @@ func (p *clientAPI) CreateAccount(ctx context.Context, cMsg messages.FromClientA
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) CreateStatus(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) CreateStatus(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
status, ok := cMsg.GTSModel.(*gtsmodel.Status)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Status", cMsg.GTSModel)
|
||||
}
|
||||
|
||||
// Update stats for the actor account.
|
||||
if err := p.utilF.incrementStatusesCount(ctx, cMsg.OriginAccount, status); err != nil {
|
||||
if err := p.utils.incrementStatusesCount(ctx, cMsg.Origin, status); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -269,7 +254,7 @@ func (p *clientAPI) CreateStatus(ctx context.Context, cMsg messages.FromClientAP
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) CreatePollVote(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) CreatePollVote(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
// Cast the create poll vote attached to message.
|
||||
vote, ok := cMsg.GTSModel.(*gtsmodel.PollVote)
|
||||
if !ok {
|
||||
|
@ -310,14 +295,14 @@ func (p *clientAPI) CreatePollVote(ctx context.Context, cMsg messages.FromClient
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) CreateFollowReq(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) CreateFollowReq(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
followRequest, ok := cMsg.GTSModel.(*gtsmodel.FollowRequest)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.FollowRequest", cMsg.GTSModel)
|
||||
}
|
||||
|
||||
// Update stats for the target account.
|
||||
if err := p.utilF.incrementFollowRequestsCount(ctx, cMsg.TargetAccount); err != nil {
|
||||
if err := p.utils.incrementFollowRequestsCount(ctx, cMsg.Target); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -338,7 +323,7 @@ func (p *clientAPI) CreateFollowReq(ctx context.Context, cMsg messages.FromClien
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) CreateLike(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) CreateLike(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
fave, ok := cMsg.GTSModel.(*gtsmodel.StatusFave)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.StatusFave", cMsg.GTSModel)
|
||||
|
@ -364,14 +349,14 @@ func (p *clientAPI) CreateLike(ctx context.Context, cMsg messages.FromClientAPI)
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) CreateAnnounce(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) CreateAnnounce(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
boost, ok := cMsg.GTSModel.(*gtsmodel.Status)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Status", cMsg.GTSModel)
|
||||
}
|
||||
|
||||
// Update stats for the actor account.
|
||||
if err := p.utilF.incrementStatusesCount(ctx, cMsg.OriginAccount, boost); err != nil {
|
||||
if err := p.utils.incrementStatusesCount(ctx, cMsg.Origin, boost); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -396,7 +381,7 @@ func (p *clientAPI) CreateAnnounce(ctx context.Context, cMsg messages.FromClient
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) CreateBlock(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) CreateBlock(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
block, ok := cMsg.GTSModel.(*gtsmodel.Block)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Block", cMsg.GTSModel)
|
||||
|
@ -430,7 +415,7 @@ func (p *clientAPI) CreateBlock(ctx context.Context, cMsg messages.FromClientAPI
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) UpdateStatus(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) UpdateStatus(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
// Cast the updated Status model attached to msg.
|
||||
status, ok := cMsg.GTSModel.(*gtsmodel.Status)
|
||||
if !ok {
|
||||
|
@ -462,7 +447,7 @@ func (p *clientAPI) UpdateStatus(ctx context.Context, cMsg messages.FromClientAP
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) UpdateAccount(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) UpdateAccount(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
account, ok := cMsg.GTSModel.(*gtsmodel.Account)
|
||||
if !ok {
|
||||
return gtserror.Newf("cannot cast %T -> *gtsmodel.Account", cMsg.GTSModel)
|
||||
|
@ -475,7 +460,7 @@ func (p *clientAPI) UpdateAccount(ctx context.Context, cMsg messages.FromClientA
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) UpdateReport(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) UpdateReport(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
report, ok := cMsg.GTSModel.(*gtsmodel.Report)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Report", cMsg.GTSModel)
|
||||
|
@ -494,23 +479,23 @@ func (p *clientAPI) UpdateReport(ctx context.Context, cMsg messages.FromClientAP
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) AcceptFollow(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) AcceptFollow(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
follow, ok := cMsg.GTSModel.(*gtsmodel.Follow)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Follow", cMsg.GTSModel)
|
||||
}
|
||||
|
||||
// Update stats for the target account.
|
||||
if err := p.utilF.decrementFollowRequestsCount(ctx, cMsg.TargetAccount); err != nil {
|
||||
if err := p.utils.decrementFollowRequestsCount(ctx, cMsg.Target); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
if err := p.utilF.incrementFollowersCount(ctx, cMsg.TargetAccount); err != nil {
|
||||
if err := p.utils.incrementFollowersCount(ctx, cMsg.Target); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
// Update stats for the origin account.
|
||||
if err := p.utilF.incrementFollowingCount(ctx, cMsg.OriginAccount); err != nil {
|
||||
if err := p.utils.incrementFollowingCount(ctx, cMsg.Origin); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -525,14 +510,14 @@ func (p *clientAPI) AcceptFollow(ctx context.Context, cMsg messages.FromClientAP
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) RejectFollowRequest(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) RejectFollowRequest(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
followReq, ok := cMsg.GTSModel.(*gtsmodel.FollowRequest)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.FollowRequest", cMsg.GTSModel)
|
||||
}
|
||||
|
||||
// Update stats for the target account.
|
||||
if err := p.utilF.decrementFollowRequestsCount(ctx, cMsg.TargetAccount); err != nil {
|
||||
if err := p.utils.decrementFollowRequestsCount(ctx, cMsg.Target); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -546,19 +531,19 @@ func (p *clientAPI) RejectFollowRequest(ctx context.Context, cMsg messages.FromC
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) UndoFollow(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) UndoFollow(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
follow, ok := cMsg.GTSModel.(*gtsmodel.Follow)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Follow", cMsg.GTSModel)
|
||||
}
|
||||
|
||||
// Update stats for the origin account.
|
||||
if err := p.utilF.decrementFollowingCount(ctx, cMsg.OriginAccount); err != nil {
|
||||
if err := p.utils.decrementFollowingCount(ctx, cMsg.Origin); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
// Update stats for the target account.
|
||||
if err := p.utilF.decrementFollowersCount(ctx, cMsg.TargetAccount); err != nil {
|
||||
if err := p.utils.decrementFollowersCount(ctx, cMsg.Target); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -569,7 +554,7 @@ func (p *clientAPI) UndoFollow(ctx context.Context, cMsg messages.FromClientAPI)
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) UndoBlock(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) UndoBlock(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
block, ok := cMsg.GTSModel.(*gtsmodel.Block)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Block", cMsg.GTSModel)
|
||||
|
@ -582,7 +567,7 @@ func (p *clientAPI) UndoBlock(ctx context.Context, cMsg messages.FromClientAPI)
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) UndoFave(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) UndoFave(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
statusFave, ok := cMsg.GTSModel.(*gtsmodel.StatusFave)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.StatusFave", cMsg.GTSModel)
|
||||
|
@ -599,7 +584,7 @@ func (p *clientAPI) UndoFave(ctx context.Context, cMsg messages.FromClientAPI) e
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) UndoAnnounce(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) UndoAnnounce(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
status, ok := cMsg.GTSModel.(*gtsmodel.Status)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Status", cMsg.GTSModel)
|
||||
|
@ -610,7 +595,7 @@ func (p *clientAPI) UndoAnnounce(ctx context.Context, cMsg messages.FromClientAP
|
|||
}
|
||||
|
||||
// Update stats for the origin account.
|
||||
if err := p.utilF.decrementStatusesCount(ctx, cMsg.OriginAccount); err != nil {
|
||||
if err := p.utils.decrementStatusesCount(ctx, cMsg.Origin); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -629,7 +614,7 @@ func (p *clientAPI) UndoAnnounce(ctx context.Context, cMsg messages.FromClientAP
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) DeleteStatus(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) DeleteStatus(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
// Don't delete attachments, just unattach them:
|
||||
// this request comes from the client API and the
|
||||
// poster may want to use attachments again later.
|
||||
|
@ -648,12 +633,26 @@ func (p *clientAPI) DeleteStatus(ctx context.Context, cMsg messages.FromClientAP
|
|||
return gtserror.Newf("db error populating status: %w", err)
|
||||
}
|
||||
|
||||
if err := p.utilF.wipeStatus(ctx, status, deleteAttachments); err != nil {
|
||||
// Drop any outgoing queued AP requests about / targeting
|
||||
// this status, (stops queued likes, boosts, creates etc).
|
||||
p.state.Workers.Delivery.Queue.Delete("ObjectID", status.URI)
|
||||
p.state.Workers.Delivery.Queue.Delete("TargetID", status.URI)
|
||||
|
||||
// Drop any incoming queued client messages about / targeting
|
||||
// status, (stops processing of local origin data for status).
|
||||
p.state.Workers.Client.Queue.Delete("TargetURI", status.URI)
|
||||
|
||||
// Drop any incoming queued federator messages targeting status,
|
||||
// (stops processing of remote origin data targeting this status).
|
||||
p.state.Workers.Federator.Queue.Delete("TargetURI", status.URI)
|
||||
|
||||
// First perform the actual status deletion.
|
||||
if err := p.utils.wipeStatus(ctx, status, deleteAttachments); err != nil {
|
||||
log.Errorf(ctx, "error wiping status: %v", err)
|
||||
}
|
||||
|
||||
// Update stats for the origin account.
|
||||
if err := p.utilF.decrementStatusesCount(ctx, cMsg.OriginAccount); err != nil {
|
||||
if err := p.utils.decrementStatusesCount(ctx, cMsg.Origin); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -670,7 +669,7 @@ func (p *clientAPI) DeleteStatus(ctx context.Context, cMsg messages.FromClientAP
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) DeleteAccount(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) DeleteAccount(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
// The originID of the delete, one of:
|
||||
// - ID of a domain block, for which
|
||||
// this account delete is a side effect.
|
||||
|
@ -684,21 +683,41 @@ func (p *clientAPI) DeleteAccount(ctx context.Context, cMsg messages.FromClientA
|
|||
} else {
|
||||
// Origin is whichever account
|
||||
// originated this message.
|
||||
originID = cMsg.OriginAccount.ID
|
||||
originID = cMsg.Origin.ID
|
||||
}
|
||||
|
||||
if err := p.federate.DeleteAccount(ctx, cMsg.TargetAccount); err != nil {
|
||||
// Extract target account.
|
||||
account := cMsg.Target
|
||||
|
||||
// Drop any outgoing queued AP requests to / from / targeting
|
||||
// this account, (stops queued likes, boosts, creates etc).
|
||||
p.state.Workers.Delivery.Queue.Delete("ActorID", account.URI)
|
||||
p.state.Workers.Delivery.Queue.Delete("ObjectID", account.URI)
|
||||
p.state.Workers.Delivery.Queue.Delete("TargetID", account.URI)
|
||||
|
||||
// Drop any incoming queued client messages to / from this
|
||||
// account, (stops processing of local origin data for acccount).
|
||||
p.state.Workers.Client.Queue.Delete("Origin.ID", account.ID)
|
||||
p.state.Workers.Client.Queue.Delete("Target.ID", account.ID)
|
||||
p.state.Workers.Client.Queue.Delete("TargetURI", account.URI)
|
||||
|
||||
// Drop any incoming queued federator messages to this account,
|
||||
// (stops processing of remote origin data targeting this account).
|
||||
p.state.Workers.Federator.Queue.Delete("Receiving.ID", account.ID)
|
||||
p.state.Workers.Federator.Queue.Delete("TargetURI", account.URI)
|
||||
|
||||
if err := p.federate.DeleteAccount(ctx, cMsg.Target); err != nil {
|
||||
log.Errorf(ctx, "error federating account delete: %v", err)
|
||||
}
|
||||
|
||||
if err := p.account.Delete(ctx, cMsg.TargetAccount, originID); err != nil {
|
||||
if err := p.account.Delete(ctx, cMsg.Target, originID); err != nil {
|
||||
log.Errorf(ctx, "error deleting account: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) ReportAccount(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) ReportAccount(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
report, ok := cMsg.GTSModel.(*gtsmodel.Report)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Report", cMsg.GTSModel)
|
||||
|
@ -719,28 +738,28 @@ func (p *clientAPI) ReportAccount(ctx context.Context, cMsg messages.FromClientA
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) MoveAccount(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) MoveAccount(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
// Redirect each local follower of
|
||||
// OriginAccount to follow move target.
|
||||
p.utilF.redirectFollowers(ctx, cMsg.OriginAccount, cMsg.TargetAccount)
|
||||
p.utils.redirectFollowers(ctx, cMsg.Origin, cMsg.Target)
|
||||
|
||||
// At this point, we know OriginAccount has the
|
||||
// Move set on it. Just make sure it's populated.
|
||||
if err := p.state.DB.PopulateMove(ctx, cMsg.OriginAccount.Move); err != nil {
|
||||
if err := p.state.DB.PopulateMove(ctx, cMsg.Origin.Move); err != nil {
|
||||
return gtserror.Newf("error populating Move: %w", err)
|
||||
}
|
||||
|
||||
// Now send the Move message out to
|
||||
// OriginAccount's (remote) followers.
|
||||
if err := p.federate.MoveAccount(ctx, cMsg.OriginAccount); err != nil {
|
||||
if err := p.federate.MoveAccount(ctx, cMsg.Origin); err != nil {
|
||||
return gtserror.Newf("error federating account move: %w", err)
|
||||
}
|
||||
|
||||
// Mark the move attempt as successful.
|
||||
cMsg.OriginAccount.Move.SucceededAt = cMsg.OriginAccount.Move.AttemptedAt
|
||||
cMsg.Origin.Move.SucceededAt = cMsg.Origin.Move.AttemptedAt
|
||||
if err := p.state.DB.UpdateMove(
|
||||
ctx,
|
||||
cMsg.OriginAccount.Move,
|
||||
cMsg.Origin.Move,
|
||||
"succeeded_at",
|
||||
); err != nil {
|
||||
return gtserror.Newf("error marking move as successful: %w", err)
|
||||
|
@ -749,7 +768,7 @@ func (p *clientAPI) MoveAccount(ctx context.Context, cMsg messages.FromClientAPI
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) AcceptAccount(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) AcceptAccount(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
newUser, ok := cMsg.GTSModel.(*gtsmodel.User)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.User", cMsg.GTSModel)
|
||||
|
@ -772,17 +791,17 @@ func (p *clientAPI) AcceptAccount(ctx context.Context, cMsg messages.FromClientA
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *clientAPI) RejectAccount(ctx context.Context, cMsg messages.FromClientAPI) error {
|
||||
func (p *clientAPI) RejectAccount(ctx context.Context, cMsg *messages.FromClientAPI) error {
|
||||
deniedUser, ok := cMsg.GTSModel.(*gtsmodel.DeniedUser)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.DeniedUser", cMsg.GTSModel)
|
||||
}
|
||||
|
||||
// Remove the account.
|
||||
if err := p.state.DB.DeleteAccount(ctx, cMsg.TargetAccount.ID); err != nil {
|
||||
if err := p.state.DB.DeleteAccount(ctx, cMsg.Target.ID); err != nil {
|
||||
log.Errorf(ctx,
|
||||
"db error deleting account %s: %v",
|
||||
cMsg.TargetAccount.ID, err,
|
||||
cMsg.Target.ID, err,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -197,11 +197,11 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusWithNotification() {
|
|||
// Process the new status.
|
||||
if err := suite.processor.Workers().ProcessFromClientAPI(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
OriginAccount: postingAccount,
|
||||
Origin: postingAccount,
|
||||
},
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
@ -291,11 +291,11 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReply() {
|
|||
// Process the new status.
|
||||
if err := suite.processor.Workers().ProcessFromClientAPI(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
OriginAccount: postingAccount,
|
||||
Origin: postingAccount,
|
||||
},
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
@ -355,11 +355,11 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyMuted() {
|
|||
// Process the new status.
|
||||
if err := suite.processor.Workers().ProcessFromClientAPI(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
OriginAccount: postingAccount,
|
||||
Origin: postingAccount,
|
||||
},
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
@ -409,11 +409,11 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoostMuted() {
|
|||
// Process the new status.
|
||||
if err := suite.processor.Workers().ProcessFromClientAPI(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
OriginAccount: postingAccount,
|
||||
Origin: postingAccount,
|
||||
},
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
@ -467,11 +467,11 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyLis
|
|||
// Process the new status.
|
||||
if err := suite.processor.Workers().ProcessFromClientAPI(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
OriginAccount: postingAccount,
|
||||
Origin: postingAccount,
|
||||
},
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
@ -540,11 +540,11 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusListRepliesPolicyLis
|
|||
// Process the new status.
|
||||
if err := suite.processor.Workers().ProcessFromClientAPI(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
OriginAccount: postingAccount,
|
||||
Origin: postingAccount,
|
||||
},
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
@ -608,11 +608,11 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusReplyListRepliesPoli
|
|||
// Process the new status.
|
||||
if err := suite.processor.Workers().ProcessFromClientAPI(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
OriginAccount: postingAccount,
|
||||
Origin: postingAccount,
|
||||
},
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
@ -664,11 +664,11 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoost() {
|
|||
// Process the new status.
|
||||
if err := suite.processor.Workers().ProcessFromClientAPI(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
OriginAccount: postingAccount,
|
||||
Origin: postingAccount,
|
||||
},
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
@ -729,11 +729,11 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusBoostNoReblogs() {
|
|||
// Process the new status.
|
||||
if err := suite.processor.Workers().ProcessFromClientAPI(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: status,
|
||||
OriginAccount: postingAccount,
|
||||
Origin: postingAccount,
|
||||
},
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
@ -776,11 +776,11 @@ func (suite *FromClientAPITestSuite) TestProcessStatusDelete() {
|
|||
// Process the status delete.
|
||||
if err := suite.processor.Workers().ProcessFromClientAPI(
|
||||
ctx,
|
||||
messages.FromClientAPI{
|
||||
&messages.FromClientAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: deletedStatus,
|
||||
OriginAccount: deletingAccount,
|
||||
Origin: deletingAccount,
|
||||
},
|
||||
); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
|
|
|
@ -19,13 +19,14 @@ package workers
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"codeberg.org/gruf/go-kv"
|
||||
"codeberg.org/gruf/go-logger/v2/level"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/federation/dereferencing"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
|
@ -43,34 +44,20 @@ type fediAPI struct {
|
|||
surface *surface
|
||||
federate *federate
|
||||
account *account.Processor
|
||||
utilF *utilF
|
||||
utils *utils
|
||||
}
|
||||
|
||||
func (p *Processor) EnqueueFediAPI(cctx context.Context, msgs ...messages.FromFediAPI) {
|
||||
_ = p.workers.Federator.MustEnqueueCtx(cctx, func(wctx context.Context) {
|
||||
// Copy caller ctx values to worker's.
|
||||
wctx = gtscontext.WithValues(wctx, cctx)
|
||||
|
||||
// Process worker messages.
|
||||
for _, msg := range msgs {
|
||||
if err := p.ProcessFromFediAPI(wctx, msg); err != nil {
|
||||
log.Errorf(wctx, "error processing fedi API message: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
// Allocate new log fields slice
|
||||
fields := make([]kv.Field, 3, 5)
|
||||
fields[0] = kv.Field{"activityType", fMsg.APActivityType}
|
||||
fields[1] = kv.Field{"objectType", fMsg.APObjectType}
|
||||
fields[2] = kv.Field{"toAccount", fMsg.ReceivingAccount.Username}
|
||||
fields[2] = kv.Field{"toAccount", fMsg.Receiving.Username}
|
||||
|
||||
if fMsg.APIri != nil {
|
||||
if fMsg.APIRI != nil {
|
||||
// An IRI was supplied, append to log
|
||||
fields = append(fields, kv.Field{
|
||||
"iri", fMsg.APIri,
|
||||
"iri", fMsg.APIRI,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -168,7 +155,7 @@ func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg messages.FromFe
|
|||
return gtserror.Newf("unhandled: %s %s", fMsg.APActivityType, fMsg.APObjectType)
|
||||
}
|
||||
|
||||
func (p *fediAPI) CreateStatus(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) CreateStatus(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
var (
|
||||
status *gtsmodel.Status
|
||||
statusable ap.Statusable
|
||||
|
@ -178,11 +165,11 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg messages.FromFediAPI) e
|
|||
var ok bool
|
||||
|
||||
switch {
|
||||
case fMsg.APObjectModel != nil:
|
||||
case fMsg.APObject != nil:
|
||||
// A model was provided, extract this from message.
|
||||
statusable, ok = fMsg.APObjectModel.(ap.Statusable)
|
||||
statusable, ok = fMsg.APObject.(ap.Statusable)
|
||||
if !ok {
|
||||
return gtserror.Newf("cannot cast %T -> ap.Statusable", fMsg.APObjectModel)
|
||||
return gtserror.Newf("cannot cast %T -> ap.Statusable", fMsg.APObject)
|
||||
}
|
||||
|
||||
// Create bare-bones model to pass
|
||||
|
@ -196,7 +183,7 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg messages.FromFediAPI) e
|
|||
// statusable model, which it will use to further flesh out
|
||||
// the bare bones model and insert it into the database.
|
||||
status, statusable, err = p.federate.RefreshStatus(ctx,
|
||||
fMsg.ReceivingAccount.Username,
|
||||
fMsg.Receiving.Username,
|
||||
bareStatus,
|
||||
statusable,
|
||||
// Force refresh within 5min window.
|
||||
|
@ -206,15 +193,15 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg messages.FromFediAPI) e
|
|||
return gtserror.Newf("error processing new status %s: %w", bareStatus.URI, err)
|
||||
}
|
||||
|
||||
case fMsg.APIri != nil:
|
||||
case fMsg.APIRI != nil:
|
||||
// Model was not set, deref with IRI (this is a forward).
|
||||
// This will also cause the status to be inserted into the db.
|
||||
status, statusable, err = p.federate.GetStatusByURI(ctx,
|
||||
fMsg.ReceivingAccount.Username,
|
||||
fMsg.APIri,
|
||||
fMsg.Receiving.Username,
|
||||
fMsg.APIRI,
|
||||
)
|
||||
if err != nil {
|
||||
return gtserror.Newf("error dereferencing forwarded status %s: %w", fMsg.APIri, err)
|
||||
return gtserror.Newf("error dereferencing forwarded status %s: %w", fMsg.APIRI, err)
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -230,7 +217,7 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg messages.FromFediAPI) e
|
|||
}
|
||||
|
||||
// Update stats for the remote account.
|
||||
if err := p.utilF.incrementStatusesCount(ctx, fMsg.RequestingAccount, status); err != nil {
|
||||
if err := p.utils.incrementStatusesCount(ctx, fMsg.Requesting, status); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -248,7 +235,7 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg messages.FromFediAPI) e
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) CreatePollVote(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) CreatePollVote(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
// Cast poll vote type from the worker message.
|
||||
vote, ok := fMsg.GTSModel.(*gtsmodel.PollVote)
|
||||
if !ok {
|
||||
|
@ -293,7 +280,7 @@ func (p *fediAPI) CreatePollVote(ctx context.Context, fMsg messages.FromFediAPI)
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) CreateFollowReq(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) CreateFollowReq(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
followRequest, ok := fMsg.GTSModel.(*gtsmodel.FollowRequest)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.FollowRequest", fMsg.GTSModel)
|
||||
|
@ -310,7 +297,7 @@ func (p *fediAPI) CreateFollowReq(ctx context.Context, fMsg messages.FromFediAPI
|
|||
}
|
||||
|
||||
// And update stats for the local account.
|
||||
if err := p.utilF.incrementFollowRequestsCount(ctx, fMsg.ReceivingAccount); err != nil {
|
||||
if err := p.utils.incrementFollowRequestsCount(ctx, fMsg.Receiving); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -330,12 +317,12 @@ func (p *fediAPI) CreateFollowReq(ctx context.Context, fMsg messages.FromFediAPI
|
|||
}
|
||||
|
||||
// Update stats for the local account.
|
||||
if err := p.utilF.incrementFollowersCount(ctx, fMsg.ReceivingAccount); err != nil {
|
||||
if err := p.utils.incrementFollowersCount(ctx, fMsg.Receiving); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
// Update stats for the remote account.
|
||||
if err := p.utilF.incrementFollowingCount(ctx, fMsg.RequestingAccount); err != nil {
|
||||
if err := p.utils.incrementFollowingCount(ctx, fMsg.Requesting); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -350,7 +337,7 @@ func (p *fediAPI) CreateFollowReq(ctx context.Context, fMsg messages.FromFediAPI
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) CreateLike(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) CreateLike(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
fave, ok := fMsg.GTSModel.(*gtsmodel.StatusFave)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.StatusFave", fMsg.GTSModel)
|
||||
|
@ -372,7 +359,7 @@ func (p *fediAPI) CreateLike(ctx context.Context, fMsg messages.FromFediAPI) err
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
boost, ok := fMsg.GTSModel.(*gtsmodel.Status)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Status", fMsg.GTSModel)
|
||||
|
@ -386,7 +373,7 @@ func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg messages.FromFediAPI)
|
|||
boost, err = p.federate.EnrichAnnounce(
|
||||
ctx,
|
||||
boost,
|
||||
fMsg.ReceivingAccount.Username,
|
||||
fMsg.Receiving.Username,
|
||||
)
|
||||
if err != nil {
|
||||
if gtserror.IsUnretrievable(err) {
|
||||
|
@ -400,7 +387,7 @@ func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg messages.FromFediAPI)
|
|||
}
|
||||
|
||||
// Update stats for the remote account.
|
||||
if err := p.utilF.incrementStatusesCount(ctx, fMsg.RequestingAccount, boost); err != nil {
|
||||
if err := p.utils.incrementStatusesCount(ctx, fMsg.Requesting, boost); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -420,7 +407,7 @@ func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg messages.FromFediAPI)
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) CreateBlock(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) CreateBlock(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
block, ok := fMsg.GTSModel.(*gtsmodel.Block)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Block", fMsg.GTSModel)
|
||||
|
@ -499,7 +486,7 @@ func (p *fediAPI) CreateBlock(ctx context.Context, fMsg messages.FromFediAPI) er
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) CreateFlag(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) CreateFlag(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
incomingReport, ok := fMsg.GTSModel.(*gtsmodel.Report)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Report", fMsg.GTSModel)
|
||||
|
@ -515,7 +502,7 @@ func (p *fediAPI) CreateFlag(ctx context.Context, fMsg messages.FromFediAPI) err
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) UpdateAccount(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) UpdateAccount(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
// Parse the old/existing account model.
|
||||
account, ok := fMsg.GTSModel.(*gtsmodel.Account)
|
||||
if !ok {
|
||||
|
@ -523,15 +510,15 @@ func (p *fediAPI) UpdateAccount(ctx context.Context, fMsg messages.FromFediAPI)
|
|||
}
|
||||
|
||||
// Because this was an Update, the new Accountable should be set on the message.
|
||||
apubAcc, ok := fMsg.APObjectModel.(ap.Accountable)
|
||||
apubAcc, ok := fMsg.APObject.(ap.Accountable)
|
||||
if !ok {
|
||||
return gtserror.Newf("cannot cast %T -> ap.Accountable", fMsg.APObjectModel)
|
||||
return gtserror.Newf("cannot cast %T -> ap.Accountable", fMsg.APObject)
|
||||
}
|
||||
|
||||
// Fetch up-to-date bio, avatar, header, etc.
|
||||
_, _, err := p.federate.RefreshAccount(
|
||||
ctx,
|
||||
fMsg.ReceivingAccount.Username,
|
||||
fMsg.Receiving.Username,
|
||||
account,
|
||||
apubAcc,
|
||||
// Force refresh within 5min window.
|
||||
|
@ -544,25 +531,25 @@ func (p *fediAPI) UpdateAccount(ctx context.Context, fMsg messages.FromFediAPI)
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) AcceptFollow(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) AcceptFollow(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
// Update stats for the remote account.
|
||||
if err := p.utilF.decrementFollowRequestsCount(ctx, fMsg.RequestingAccount); err != nil {
|
||||
if err := p.utils.decrementFollowRequestsCount(ctx, fMsg.Requesting); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
if err := p.utilF.incrementFollowersCount(ctx, fMsg.RequestingAccount); err != nil {
|
||||
if err := p.utils.incrementFollowersCount(ctx, fMsg.Requesting); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
// Update stats for the local account.
|
||||
if err := p.utilF.incrementFollowingCount(ctx, fMsg.ReceivingAccount); err != nil {
|
||||
if err := p.utils.incrementFollowingCount(ctx, fMsg.Receiving); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) UpdateStatus(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) UpdateStatus(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
// Cast the existing Status model attached to msg.
|
||||
existing, ok := fMsg.GTSModel.(*gtsmodel.Status)
|
||||
if !ok {
|
||||
|
@ -570,12 +557,12 @@ func (p *fediAPI) UpdateStatus(ctx context.Context, fMsg messages.FromFediAPI) e
|
|||
}
|
||||
|
||||
// Cast the updated ActivityPub statusable object .
|
||||
apStatus, _ := fMsg.APObjectModel.(ap.Statusable)
|
||||
apStatus, _ := fMsg.APObject.(ap.Statusable)
|
||||
|
||||
// Fetch up-to-date attach status attachments, etc.
|
||||
status, _, err := p.federate.RefreshStatus(
|
||||
ctx,
|
||||
fMsg.ReceivingAccount.Username,
|
||||
fMsg.Receiving.Username,
|
||||
existing,
|
||||
apStatus,
|
||||
// Force refresh within 5min window.
|
||||
|
@ -605,7 +592,7 @@ func (p *fediAPI) UpdateStatus(ctx context.Context, fMsg messages.FromFediAPI) e
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) DeleteStatus(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) DeleteStatus(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
// Delete attachments from this status, since this request
|
||||
// comes from the federating API, and there's no way the
|
||||
// poster can do a delete + redraft for it on our instance.
|
||||
|
@ -616,12 +603,34 @@ func (p *fediAPI) DeleteStatus(ctx context.Context, fMsg messages.FromFediAPI) e
|
|||
return gtserror.Newf("%T not parseable as *gtsmodel.Status", fMsg.GTSModel)
|
||||
}
|
||||
|
||||
if err := p.utilF.wipeStatus(ctx, status, deleteAttachments); err != nil {
|
||||
// Try to populate status structs if possible,
|
||||
// in order to more thoroughly remove them.
|
||||
if err := p.state.DB.PopulateStatus(
|
||||
ctx, status,
|
||||
); err != nil && !errors.Is(err, db.ErrNoEntries) {
|
||||
return gtserror.Newf("db error populating status: %w", err)
|
||||
}
|
||||
|
||||
// Drop any outgoing queued AP requests about / targeting
|
||||
// this status, (stops queued likes, boosts, creates etc).
|
||||
p.state.Workers.Delivery.Queue.Delete("ObjectID", status.URI)
|
||||
p.state.Workers.Delivery.Queue.Delete("TargetID", status.URI)
|
||||
|
||||
// Drop any incoming queued client messages about / targeting
|
||||
// status, (stops processing of local origin data for status).
|
||||
p.state.Workers.Client.Queue.Delete("TargetURI", status.URI)
|
||||
|
||||
// Drop any incoming queued federator messages targeting status,
|
||||
// (stops processing of remote origin data targeting this status).
|
||||
p.state.Workers.Federator.Queue.Delete("TargetURI", status.URI)
|
||||
|
||||
// First perform the actual status deletion.
|
||||
if err := p.utils.wipeStatus(ctx, status, deleteAttachments); err != nil {
|
||||
log.Errorf(ctx, "error wiping status: %v", err)
|
||||
}
|
||||
|
||||
// Update stats for the remote account.
|
||||
if err := p.utilF.decrementStatusesCount(ctx, fMsg.RequestingAccount); err != nil {
|
||||
if err := p.utils.decrementStatusesCount(ctx, fMsg.Requesting); err != nil {
|
||||
log.Errorf(ctx, "error updating account stats: %v", err)
|
||||
}
|
||||
|
||||
|
@ -634,12 +643,28 @@ func (p *fediAPI) DeleteStatus(ctx context.Context, fMsg messages.FromFediAPI) e
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *fediAPI) DeleteAccount(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
func (p *fediAPI) DeleteAccount(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
account, ok := fMsg.GTSModel.(*gtsmodel.Account)
|
||||
if !ok {
|
||||
return gtserror.Newf("%T not parseable as *gtsmodel.Account", fMsg.GTSModel)
|
||||
}
|
||||
|
||||
// Drop any outgoing queued AP requests to / from / targeting
|
||||
// this account, (stops queued likes, boosts, creates etc).
|
||||
p.state.Workers.Delivery.Queue.Delete("ObjectID", account.URI)
|
||||
p.state.Workers.Delivery.Queue.Delete("TargetID", account.URI)
|
||||
|
||||
// Drop any incoming queued client messages to / from this
|
||||
// account, (stops processing of local origin data for acccount).
|
||||
p.state.Workers.Client.Queue.Delete("Target.ID", account.ID)
|
||||
p.state.Workers.Client.Queue.Delete("TargetURI", account.URI)
|
||||
|
||||
// Drop any incoming queued federator messages to this account,
|
||||
// (stops processing of remote origin data targeting this account).
|
||||
p.state.Workers.Federator.Queue.Delete("Requesting.ID", account.ID)
|
||||
p.state.Workers.Federator.Queue.Delete("TargetURI", account.URI)
|
||||
|
||||
// First perform the actual account deletion.
|
||||
if err := p.account.Delete(ctx, account, account.ID); err != nil {
|
||||
log.Errorf(ctx, "error deleting account: %v", err)
|
||||
}
|
||||
|
|
|
@ -220,10 +220,7 @@ func (p *fediAPI) GetOrCreateMove(
|
|||
// APActivityType: "Move"
|
||||
// GTSModel: stub *gtsmodel.Move.
|
||||
// ReceivingAccount: Account of inbox owner receiving the Move.
|
||||
func (p *fediAPI) MoveAccount(ctx context.Context, fMsg messages.FromFediAPI) error {
|
||||
// The account who received the Move message.
|
||||
receiver := fMsg.ReceivingAccount
|
||||
|
||||
func (p *fediAPI) MoveAccount(ctx context.Context, fMsg *messages.FromFediAPI) error {
|
||||
// *gtsmodel.Move activity.
|
||||
stubMove, ok := fMsg.GTSModel.(*gtsmodel.Move)
|
||||
if !ok {
|
||||
|
@ -236,7 +233,7 @@ func (p *fediAPI) MoveAccount(ctx context.Context, fMsg messages.FromFediAPI) er
|
|||
// Move origin and target info.
|
||||
var (
|
||||
originAcctURIStr = stubMove.OriginURI
|
||||
originAcct = fMsg.RequestingAccount
|
||||
originAcct = fMsg.Requesting
|
||||
targetAcctURIStr = stubMove.TargetURI
|
||||
targetAcctURI = stubMove.Target
|
||||
)
|
||||
|
@ -308,7 +305,7 @@ func (p *fediAPI) MoveAccount(ctx context.Context, fMsg messages.FromFediAPI) er
|
|||
// Account to which the Move is taking place.
|
||||
targetAcct, targetAcctable, err := p.federate.GetAccountByURI(
|
||||
ctx,
|
||||
receiver.Username,
|
||||
fMsg.Receiving.Username,
|
||||
targetAcctURI,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -340,7 +337,7 @@ func (p *fediAPI) MoveAccount(ctx context.Context, fMsg messages.FromFediAPI) er
|
|||
// Force refresh Move target account
|
||||
// to ensure we have up-to-date version.
|
||||
targetAcct, _, err = p.federate.RefreshAccount(ctx,
|
||||
receiver.Username,
|
||||
fMsg.Receiving.Username,
|
||||
targetAcct,
|
||||
targetAcctable,
|
||||
dereferencing.Freshest,
|
||||
|
@ -379,7 +376,7 @@ func (p *fediAPI) MoveAccount(ctx context.Context, fMsg messages.FromFediAPI) er
|
|||
|
||||
// Transfer originAcct's followers
|
||||
// on this instance to targetAcct.
|
||||
redirectOK := p.utilF.redirectFollowers(
|
||||
redirectOK := p.utils.redirectFollowers(
|
||||
ctx,
|
||||
originAcct,
|
||||
targetAcct,
|
||||
|
|
|
@ -54,12 +54,12 @@ func (suite *FromFediAPITestSuite) TestProcessFederationAnnounce() {
|
|||
announceStatus.Account = boostingAccount
|
||||
announceStatus.Visibility = boostedStatus.Visibility
|
||||
|
||||
err := suite.processor.Workers().ProcessFromFediAPI(context.Background(), messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: announceStatus,
|
||||
ReceivingAccount: suite.testAccounts["local_account_1"],
|
||||
RequestingAccount: boostingAccount,
|
||||
err := suite.processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityAnnounce,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: announceStatus,
|
||||
Receiving: suite.testAccounts["local_account_1"],
|
||||
Requesting: boostingAccount,
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
|
@ -115,12 +115,12 @@ func (suite *FromFediAPITestSuite) TestProcessReplyMention() {
|
|||
suite.NoError(errWithCode)
|
||||
|
||||
// Send the replied status off to the fedi worker to be further processed.
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(context.Background(), messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
APObjectModel: replyingStatusable,
|
||||
ReceivingAccount: repliedAccount,
|
||||
RequestingAccount: replyingAccount,
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
APObject: replyingStatusable,
|
||||
Receiving: repliedAccount,
|
||||
Requesting: replyingAccount,
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
|
@ -179,12 +179,12 @@ func (suite *FromFediAPITestSuite) TestProcessFave() {
|
|||
err := suite.db.Put(context.Background(), fave)
|
||||
suite.NoError(err)
|
||||
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(context.Background(), messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityLike,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: fave,
|
||||
ReceivingAccount: favedAccount,
|
||||
RequestingAccount: favingAccount,
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityLike,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: fave,
|
||||
Receiving: favedAccount,
|
||||
Requesting: favingAccount,
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
|
@ -249,12 +249,12 @@ func (suite *FromFediAPITestSuite) TestProcessFaveWithDifferentReceivingAccount(
|
|||
err := suite.db.Put(context.Background(), fave)
|
||||
suite.NoError(err)
|
||||
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(context.Background(), messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityLike,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: fave,
|
||||
ReceivingAccount: receivingAccount,
|
||||
RequestingAccount: favingAccount,
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(context.Background(), &messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityLike,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: fave,
|
||||
Receiving: receivingAccount,
|
||||
Requesting: favingAccount,
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
|
@ -321,12 +321,12 @@ func (suite *FromFediAPITestSuite) TestProcessAccountDelete() {
|
|||
suite.NoError(err)
|
||||
|
||||
// now they are mufos!
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: deletedAccount,
|
||||
ReceivingAccount: receivingAccount,
|
||||
RequestingAccount: deletedAccount,
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityDelete,
|
||||
GTSModel: deletedAccount,
|
||||
Receiving: receivingAccount,
|
||||
Requesting: deletedAccount,
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
|
@ -402,12 +402,12 @@ func (suite *FromFediAPITestSuite) TestProcessFollowRequestLocked() {
|
|||
err := suite.db.Put(ctx, satanFollowRequestTurtle)
|
||||
suite.NoError(err)
|
||||
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: satanFollowRequestTurtle,
|
||||
ReceivingAccount: targetAccount,
|
||||
RequestingAccount: originAccount,
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: satanFollowRequestTurtle,
|
||||
Receiving: targetAccount,
|
||||
Requesting: originAccount,
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
|
@ -456,12 +456,12 @@ func (suite *FromFediAPITestSuite) TestProcessFollowRequestUnlocked() {
|
|||
err := suite.db.Put(ctx, satanFollowRequestTurtle)
|
||||
suite.NoError(err)
|
||||
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: satanFollowRequestTurtle,
|
||||
ReceivingAccount: targetAccount,
|
||||
RequestingAccount: originAccount,
|
||||
err = suite.processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{
|
||||
APObjectType: ap.ActivityFollow,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: satanFollowRequestTurtle,
|
||||
Receiving: targetAccount,
|
||||
Requesting: originAccount,
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
|
@ -532,13 +532,13 @@ func (suite *FromFediAPITestSuite) TestCreateStatusFromIRI() {
|
|||
receivingAccount := suite.testAccounts["local_account_1"]
|
||||
statusCreator := suite.testAccounts["remote_account_2"]
|
||||
|
||||
err := suite.processor.Workers().ProcessFromFediAPI(ctx, messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: nil, // gtsmodel is nil because this is a forwarded status -- we want to dereference it using the iri
|
||||
ReceivingAccount: receivingAccount,
|
||||
RequestingAccount: statusCreator,
|
||||
APIri: testrig.URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1"),
|
||||
err := suite.processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectNote,
|
||||
APActivityType: ap.ActivityCreate,
|
||||
GTSModel: nil, // gtsmodel is nil because this is a forwarded status -- we want to dereference it using the iri
|
||||
Receiving: receivingAccount,
|
||||
Requesting: statusCreator,
|
||||
APIRI: testrig.URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1"),
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
|
@ -585,7 +585,7 @@ func (suite *FromFediAPITestSuite) TestMoveAccount() {
|
|||
}
|
||||
|
||||
// Process the Move.
|
||||
err := suite.processor.Workers().ProcessFromFediAPI(ctx, messages.FromFediAPI{
|
||||
err := suite.processor.Workers().ProcessFromFediAPI(ctx, &messages.FromFediAPI{
|
||||
APObjectType: ap.ObjectProfile,
|
||||
APActivityType: ap.ActivityMove,
|
||||
GTSModel: >smodel.Move{
|
||||
|
@ -595,8 +595,8 @@ func (suite *FromFediAPITestSuite) TestMoveAccount() {
|
|||
Target: testrig.URLMustParse(targetAcct.URI),
|
||||
URI: "https://fossbros-anonymous.io/users/foss_satan/moves/01HRA064871MR8HGVSAFJ333GM",
|
||||
},
|
||||
ReceivingAccount: receivingAcct,
|
||||
RequestingAccount: requestingAcct,
|
||||
Receiving: receivingAcct,
|
||||
Requesting: requestingAcct,
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
|
|
|
@ -32,9 +32,9 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||
)
|
||||
|
||||
// utilF wraps util functions used by both
|
||||
// util provides util functions used by both
|
||||
// the fromClientAPI and fromFediAPI functions.
|
||||
type utilF struct {
|
||||
type utils struct {
|
||||
state *state.State
|
||||
media *media.Processor
|
||||
account *account.Processor
|
||||
|
@ -45,7 +45,7 @@ type utilF struct {
|
|||
// used to totally delete a status + all
|
||||
// its attachments, notifications, boosts,
|
||||
// and timeline entries.
|
||||
func (u *utilF) wipeStatus(
|
||||
func (u *utils) wipeStatus(
|
||||
ctx context.Context,
|
||||
statusToDelete *gtsmodel.Status,
|
||||
deleteAttachments bool,
|
||||
|
@ -152,7 +152,7 @@ func (u *utilF) wipeStatus(
|
|||
// already, and the Move must be valid.
|
||||
//
|
||||
// Return bool will be true if all goes OK.
|
||||
func (u *utilF) redirectFollowers(
|
||||
func (u *utils) redirectFollowers(
|
||||
ctx context.Context,
|
||||
originAcct *gtsmodel.Account,
|
||||
targetAcct *gtsmodel.Account,
|
||||
|
@ -239,7 +239,7 @@ func (u *utilF) redirectFollowers(
|
|||
return true
|
||||
}
|
||||
|
||||
func (u *utilF) incrementStatusesCount(
|
||||
func (u *utils) incrementStatusesCount(
|
||||
ctx context.Context,
|
||||
account *gtsmodel.Account,
|
||||
status *gtsmodel.Status,
|
||||
|
@ -271,7 +271,7 @@ func (u *utilF) incrementStatusesCount(
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *utilF) decrementStatusesCount(
|
||||
func (u *utils) decrementStatusesCount(
|
||||
ctx context.Context,
|
||||
account *gtsmodel.Account,
|
||||
) error {
|
||||
|
@ -305,7 +305,7 @@ func (u *utilF) decrementStatusesCount(
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *utilF) incrementFollowersCount(
|
||||
func (u *utils) incrementFollowersCount(
|
||||
ctx context.Context,
|
||||
account *gtsmodel.Account,
|
||||
) error {
|
||||
|
@ -334,7 +334,7 @@ func (u *utilF) incrementFollowersCount(
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *utilF) decrementFollowersCount(
|
||||
func (u *utils) decrementFollowersCount(
|
||||
ctx context.Context,
|
||||
account *gtsmodel.Account,
|
||||
) error {
|
||||
|
@ -368,7 +368,7 @@ func (u *utilF) decrementFollowersCount(
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *utilF) incrementFollowingCount(
|
||||
func (u *utils) incrementFollowingCount(
|
||||
ctx context.Context,
|
||||
account *gtsmodel.Account,
|
||||
) error {
|
||||
|
@ -397,7 +397,7 @@ func (u *utilF) incrementFollowingCount(
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *utilF) decrementFollowingCount(
|
||||
func (u *utils) decrementFollowingCount(
|
||||
ctx context.Context,
|
||||
account *gtsmodel.Account,
|
||||
) error {
|
||||
|
@ -431,7 +431,7 @@ func (u *utilF) decrementFollowingCount(
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *utilF) incrementFollowRequestsCount(
|
||||
func (u *utils) incrementFollowRequestsCount(
|
||||
ctx context.Context,
|
||||
account *gtsmodel.Account,
|
||||
) error {
|
||||
|
@ -460,7 +460,7 @@ func (u *utilF) incrementFollowRequestsCount(
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *utilF) decrementFollowRequestsCount(
|
||||
func (u *utils) decrementFollowRequestsCount(
|
||||
ctx context.Context,
|
||||
account *gtsmodel.Account,
|
||||
) error {
|
||||
|
|
|
@ -30,9 +30,9 @@ import (
|
|||
)
|
||||
|
||||
type Processor struct {
|
||||
clientAPI clientAPI
|
||||
fediAPI fediAPI
|
||||
workers *workers.Workers
|
||||
clientAPI *clientAPI
|
||||
fediAPI *fediAPI
|
||||
}
|
||||
|
||||
func New(
|
||||
|
@ -45,6 +45,14 @@ func New(
|
|||
media *media.Processor,
|
||||
stream *stream.Processor,
|
||||
) Processor {
|
||||
// Init federate logic
|
||||
// wrapper struct.
|
||||
federate := &federate{
|
||||
Federator: federator,
|
||||
state: state,
|
||||
converter: converter,
|
||||
}
|
||||
|
||||
// Init surface logic
|
||||
// wrapper struct.
|
||||
surface := &surface{
|
||||
|
@ -55,16 +63,8 @@ func New(
|
|||
emailSender: emailSender,
|
||||
}
|
||||
|
||||
// Init federate logic
|
||||
// wrapper struct.
|
||||
federate := &federate{
|
||||
Federator: federator,
|
||||
state: state,
|
||||
converter: converter,
|
||||
}
|
||||
|
||||
// Init shared util funcs.
|
||||
utilF := &utilF{
|
||||
utils := &utils{
|
||||
state: state,
|
||||
media: media,
|
||||
account: account,
|
||||
|
@ -73,20 +73,20 @@ func New(
|
|||
|
||||
return Processor{
|
||||
workers: &state.Workers,
|
||||
clientAPI: &clientAPI{
|
||||
clientAPI: clientAPI{
|
||||
state: state,
|
||||
converter: converter,
|
||||
surface: surface,
|
||||
federate: federate,
|
||||
account: account,
|
||||
utilF: utilF,
|
||||
utils: utils,
|
||||
},
|
||||
fediAPI: &fediAPI{
|
||||
fediAPI: fediAPI{
|
||||
state: state,
|
||||
surface: surface,
|
||||
federate: federate,
|
||||
account: account,
|
||||
utilF: utilF,
|
||||
utils: utils,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,9 +127,6 @@ func (suite *WorkersTestSuite) SetupTest() {
|
|||
suite.processor = processing.NewProcessor(cleaner.New(&suite.state), suite.typeconverter, suite.federator, suite.oauthServer, suite.mediaManager, &suite.state, suite.emailSender)
|
||||
testrig.StartWorkers(&suite.state, suite.processor.Workers())
|
||||
|
||||
suite.state.Workers.EnqueueClientAPI = suite.processor.Workers().EnqueueClientAPI
|
||||
suite.state.Workers.EnqueueFediAPI = suite.processor.Workers().EnqueueFediAPI
|
||||
|
||||
testrig.StandardDBSetup(suite.db, suite.testAccounts)
|
||||
testrig.StandardStorageSetup(suite.storage, "../../../testrig/media")
|
||||
}
|
||||
|
|
141
internal/queue/simple.go
Normal file
141
internal/queue/simple.go
Normal file
|
@ -0,0 +1,141 @@
|
|||
// GoToSocial
|
||||
// Copyright (C) GoToSocial Authors admin@gotosocial.org
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package queue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"codeberg.org/gruf/go-list"
|
||||
)
|
||||
|
||||
// SimpleQueue provides a simple concurrency safe
|
||||
// queue using generics and a memory pool of list
|
||||
// elements to reduce overall memory usage.
|
||||
type SimpleQueue[T any] struct {
|
||||
l list.List[T]
|
||||
p []*list.Elem[T]
|
||||
w chan struct{}
|
||||
m sync.Mutex
|
||||
}
|
||||
|
||||
// Push will push given value to the queue.
|
||||
func (q *SimpleQueue[T]) Push(value T) {
|
||||
q.m.Lock()
|
||||
elem := q.alloc()
|
||||
elem.Value = value
|
||||
q.l.PushElemFront(elem)
|
||||
if q.w != nil {
|
||||
close(q.w)
|
||||
q.w = nil
|
||||
}
|
||||
q.m.Unlock()
|
||||
}
|
||||
|
||||
// Pop will attempt to pop value from the queue.
|
||||
func (q *SimpleQueue[T]) Pop() (value T, ok bool) {
|
||||
q.m.Lock()
|
||||
if ok = (q.l.Tail != nil); ok {
|
||||
tail := q.l.Tail
|
||||
value = tail.Value
|
||||
q.l.Remove(tail)
|
||||
q.free(tail)
|
||||
}
|
||||
q.m.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
// PopCtx will attempt to pop value from queue, else blocking on context.
|
||||
func (q *SimpleQueue[T]) PopCtx(ctx context.Context) (value T, ok bool) {
|
||||
|
||||
// Acquire lock.
|
||||
q.m.Lock()
|
||||
|
||||
var elem *list.Elem[T]
|
||||
|
||||
for {
|
||||
// Get next elem.
|
||||
elem = q.l.Tail
|
||||
if ok = (elem != nil); ok {
|
||||
break
|
||||
}
|
||||
|
||||
if q.w == nil {
|
||||
// Create new wait channel.
|
||||
q.w = make(chan struct{})
|
||||
}
|
||||
|
||||
// Get current
|
||||
// ch pointer.
|
||||
ch := q.w
|
||||
|
||||
// Done with lock.
|
||||
q.m.Unlock()
|
||||
|
||||
select {
|
||||
// Context canceled.
|
||||
case <-ctx.Done():
|
||||
return
|
||||
|
||||
// Pushed!
|
||||
case <-ch:
|
||||
}
|
||||
|
||||
// Relock queue.
|
||||
q.m.Lock()
|
||||
}
|
||||
|
||||
// Extract value.
|
||||
value = elem.Value
|
||||
|
||||
// Remove element.
|
||||
q.l.Remove(elem)
|
||||
q.free(elem)
|
||||
|
||||
// Done with lock.
|
||||
q.m.Unlock()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Len returns the current length of the queue.
|
||||
func (q *SimpleQueue[T]) Len() int {
|
||||
q.m.Lock()
|
||||
l := q.l.Len()
|
||||
q.m.Unlock()
|
||||
return l
|
||||
}
|
||||
|
||||
// alloc will allocate new list element (relying on memory pool).
|
||||
func (q *SimpleQueue[T]) alloc() *list.Elem[T] {
|
||||
if len(q.p) > 0 {
|
||||
elem := q.p[len(q.p)-1]
|
||||
q.p = q.p[:len(q.p)-1]
|
||||
return elem
|
||||
}
|
||||
return new(list.Elem[T])
|
||||
}
|
||||
|
||||
// free will free list element and release to pool.
|
||||
func (q *SimpleQueue[T]) free(elem *list.Elem[T]) {
|
||||
var zero T
|
||||
elem.Next = nil
|
||||
elem.Prev = nil
|
||||
elem.Value = zero
|
||||
q.p = append(q.p, elem)
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
package queue
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"context"
|
||||
|
||||
"codeberg.org/gruf/go-structr"
|
||||
)
|
||||
|
@ -26,15 +26,14 @@ import (
|
|||
// StructQueue wraps a structr.Queue{} to
|
||||
// provide simple index caching by name.
|
||||
type StructQueue[StructType any] struct {
|
||||
queue structr.Queue[StructType]
|
||||
queue structr.QueueCtx[StructType]
|
||||
index map[string]*structr.Index
|
||||
wait atomic.Pointer[chan struct{}]
|
||||
}
|
||||
|
||||
// Init initializes queue with structr.QueueConfig{}.
|
||||
func (q *StructQueue[T]) Init(config structr.QueueConfig[T]) {
|
||||
q.index = make(map[string]*structr.Index, len(config.Indices))
|
||||
q.queue = structr.Queue[T]{}
|
||||
// q.queue = structr.QueueCtx[T]{}
|
||||
q.queue.Init(config)
|
||||
for _, cfg := range config.Indices {
|
||||
q.index[cfg.Fields] = q.queue.Index(cfg.Fields)
|
||||
|
@ -43,13 +42,22 @@ func (q *StructQueue[T]) Init(config structr.QueueConfig[T]) {
|
|||
|
||||
// Pop: see structr.Queue{}.PopFront().
|
||||
func (q *StructQueue[T]) Pop() (value T, ok bool) {
|
||||
return q.queue.PopFront()
|
||||
values := q.queue.PopFrontN(1)
|
||||
if ok = (len(values) > 0); !ok {
|
||||
return
|
||||
}
|
||||
value = values[0]
|
||||
return
|
||||
}
|
||||
|
||||
// Push wraps structr.Queue{}.PushBack() to awaken those blocking on <-.Wait().
|
||||
// PopCtx: see structr.QueueCtx{}.PopFront().
|
||||
func (q *StructQueue[T]) PopCtx(ctx context.Context) (value T, ok bool) {
|
||||
return q.queue.PopFront(ctx)
|
||||
}
|
||||
|
||||
// Push: see structr.Queue.PushBack().
|
||||
func (q *StructQueue[T]) Push(values ...T) {
|
||||
q.queue.PushBack(values...)
|
||||
q.broadcast()
|
||||
}
|
||||
|
||||
// Delete pops (and drops!) all queued entries under index with key.
|
||||
|
@ -66,31 +74,5 @@ func (q *StructQueue[T]) Len() int {
|
|||
// Wait returns current wait channel, which may be
|
||||
// blocked on to awaken when new value pushed to queue.
|
||||
func (q *StructQueue[T]) Wait() <-chan struct{} {
|
||||
var ch chan struct{}
|
||||
|
||||
for {
|
||||
// Get channel ptr.
|
||||
ptr := q.wait.Load()
|
||||
if ptr != nil {
|
||||
return *ptr
|
||||
}
|
||||
|
||||
if ch == nil {
|
||||
// Allocate new channel.
|
||||
ch = make(chan struct{})
|
||||
}
|
||||
|
||||
// Try set the new wait channel ptr.
|
||||
if q.wait.CompareAndSwap(ptr, &ch) {
|
||||
return ch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// broadcast safely closes wait channel if
|
||||
// currently set, releasing waiting goroutines.
|
||||
func (q *StructQueue[T]) broadcast() {
|
||||
if ptr := q.wait.Swap(nil); ptr != nil {
|
||||
close(*ptr)
|
||||
}
|
||||
return q.queue.Wait()
|
||||
}
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/httpclient"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/queue"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
// Delivery wraps an httpclient.Request{}
|
||||
|
@ -99,29 +100,51 @@ func (p *WorkerPool) Init(client *httpclient.Client) {
|
|||
}
|
||||
|
||||
// Start will attempt to start 'n' Worker{}s.
|
||||
func (p *WorkerPool) Start(n int) (ok bool) {
|
||||
if ok = (len(p.workers) == 0); ok {
|
||||
p.workers = make([]*Worker, n)
|
||||
for i := range p.workers {
|
||||
p.workers[i] = new(Worker)
|
||||
p.workers[i].Client = p.Client
|
||||
p.workers[i].Queue = &p.Queue
|
||||
ok = p.workers[i].Start() && ok
|
||||
}
|
||||
func (p *WorkerPool) Start(n int) {
|
||||
// Check whether workers are
|
||||
// set (is already running).
|
||||
ok := (len(p.workers) > 0)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Allocate new workers slice.
|
||||
p.workers = make([]*Worker, n)
|
||||
for i := range p.workers {
|
||||
|
||||
// Allocate new Worker{}.
|
||||
p.workers[i] = new(Worker)
|
||||
p.workers[i].Client = p.Client
|
||||
p.workers[i].Queue = &p.Queue
|
||||
|
||||
// Attempt to start worker.
|
||||
// Return bool not useful
|
||||
// here, as true = started,
|
||||
// false = already running.
|
||||
_ = p.workers[i].Start()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Stop will attempt to stop contained Worker{}s.
|
||||
func (p *WorkerPool) Stop() (ok bool) {
|
||||
if ok = (len(p.workers) > 0); ok {
|
||||
for i := range p.workers {
|
||||
ok = p.workers[i].Stop() && ok
|
||||
p.workers[i] = nil
|
||||
}
|
||||
p.workers = p.workers[:0]
|
||||
func (p *WorkerPool) Stop() {
|
||||
// Check whether workers are
|
||||
// set (is currently running).
|
||||
ok := (len(p.workers) == 0)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
return
|
||||
|
||||
// Stop all running workers.
|
||||
for i := range p.workers {
|
||||
|
||||
// return bool not useful
|
||||
// here, as true = stopped,
|
||||
// false = never running.
|
||||
_ = p.workers[i].Stop()
|
||||
}
|
||||
|
||||
// Unset workers slice.
|
||||
p.workers = p.workers[:0]
|
||||
}
|
||||
|
||||
// Worker wraps an httpclient.Client{} to feed
|
||||
|
@ -158,23 +181,13 @@ func (w *Worker) run(ctx context.Context) {
|
|||
if w.Client == nil || w.Queue == nil {
|
||||
panic("not yet initialized")
|
||||
}
|
||||
log.Infof(ctx, "%p: started delivery worker", w)
|
||||
defer log.Infof(ctx, "%p: stopped delivery worker", w)
|
||||
for returned := false; !returned; {
|
||||
func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Errorf(ctx, "recovered panic: %v", r)
|
||||
}
|
||||
}()
|
||||
w.process(ctx)
|
||||
returned = true
|
||||
}()
|
||||
}
|
||||
log.Infof(ctx, "%p: starting worker", w)
|
||||
defer log.Infof(ctx, "%p: stopped worker", w)
|
||||
util.Must(func() { w.process(ctx) })
|
||||
}
|
||||
|
||||
// process is the main delivery worker processing routine.
|
||||
func (w *Worker) process(ctx context.Context) {
|
||||
func (w *Worker) process(ctx context.Context) bool {
|
||||
if w.Client == nil || w.Queue == nil {
|
||||
// we perform this check here just
|
||||
// to ensure the compiler knows these
|
||||
|
@ -188,7 +201,7 @@ loop:
|
|||
// Get next delivery.
|
||||
dlv, ok := w.next(ctx)
|
||||
if !ok {
|
||||
return
|
||||
return true
|
||||
}
|
||||
|
||||
// Check whether backoff required.
|
||||
|
@ -203,7 +216,7 @@ loop:
|
|||
// Main ctx
|
||||
// cancelled.
|
||||
backoff.Stop()
|
||||
return
|
||||
return true
|
||||
|
||||
case <-w.Queue.Wait():
|
||||
// A new message was
|
||||
|
|
|
@ -32,9 +32,7 @@ func testDeliveryWorkerPool(t *testing.T, sz int, input []*testrequest) {
|
|||
"127.0.0.0/8",
|
||||
}),
|
||||
}))
|
||||
if !wp.Start(sz) {
|
||||
t.Fatal("failed starting pool")
|
||||
}
|
||||
wp.Start(sz)
|
||||
defer wp.Stop()
|
||||
test(t, &wp.Queue, input)
|
||||
}
|
||||
|
|
68
internal/util/fns.go
Normal file
68
internal/util/fns.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
// GoToSocial
|
||||
// Copyright (C) GoToSocial Authors admin@gotosocial.org
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"codeberg.org/gruf/go-errors/v2"
|
||||
)
|
||||
|
||||
// Must executes 'fn' repeatedly until
|
||||
// it successfully returns without panic.
|
||||
func Must(fn func()) {
|
||||
if fn == nil {
|
||||
panic("nil func")
|
||||
}
|
||||
for !func() (done bool) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// Gather calling func frames.
|
||||
pcs := make([]uintptr, 10)
|
||||
n := runtime.Callers(3, pcs)
|
||||
i := runtime.CallersFrames(pcs[:n])
|
||||
c := gatherFrames(i, n)
|
||||
|
||||
const msg = "recovered panic: %v\n\n%s\n"
|
||||
fmt.Fprintf(os.Stderr, msg, r, c.String())
|
||||
}
|
||||
}()
|
||||
fn()
|
||||
done = true
|
||||
return
|
||||
}() { //nolint
|
||||
}
|
||||
}
|
||||
|
||||
// gatherFrames collates runtime frames from a frame iterator.
|
||||
func gatherFrames(iter *runtime.Frames, n int) errors.Callers {
|
||||
if iter == nil {
|
||||
return nil
|
||||
}
|
||||
frames := make([]runtime.Frame, 0, n)
|
||||
for {
|
||||
f, ok := iter.Next()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
frames = append(frames, f)
|
||||
}
|
||||
return frames
|
||||
}
|
142
internal/workers/worker_fn.go
Normal file
142
internal/workers/worker_fn.go
Normal file
|
@ -0,0 +1,142 @@
|
|||
// GoToSocial
|
||||
// Copyright (C) GoToSocial Authors admin@gotosocial.org
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package workers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"codeberg.org/gruf/go-runners"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/queue"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
// FnWorkerPool wraps multiple FnWorker{}s in
|
||||
// a singular struct for easy multi start / stop.
|
||||
type FnWorkerPool struct {
|
||||
|
||||
// Queue is embedded queue.SimpleQueue{}
|
||||
// passed to each of the pool Worker{}s.
|
||||
Queue queue.SimpleQueue[func(context.Context)]
|
||||
|
||||
// internal fields.
|
||||
workers []*FnWorker
|
||||
}
|
||||
|
||||
// Start will attempt to start 'n' FnWorker{}s.
|
||||
func (p *FnWorkerPool) Start(n int) {
|
||||
// Check whether workers are
|
||||
// set (is already running).
|
||||
ok := (len(p.workers) > 0)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Allocate new workers slice.
|
||||
p.workers = make([]*FnWorker, n)
|
||||
for i := range p.workers {
|
||||
|
||||
// Allocate new FnWorker{}.
|
||||
p.workers[i] = new(FnWorker)
|
||||
p.workers[i].Queue = &p.Queue
|
||||
|
||||
// Attempt to start worker.
|
||||
// Return bool not useful
|
||||
// here, as true = started,
|
||||
// false = already running.
|
||||
_ = p.workers[i].Start()
|
||||
}
|
||||
}
|
||||
|
||||
// Stop will attempt to stop contained FnWorker{}s.
|
||||
func (p *FnWorkerPool) Stop() {
|
||||
// Check whether workers are
|
||||
// set (is currently running).
|
||||
ok := (len(p.workers) == 0)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Stop all running workers.
|
||||
for i := range p.workers {
|
||||
|
||||
// return bool not useful
|
||||
// here, as true = stopped,
|
||||
// false = never running.
|
||||
_ = p.workers[i].Stop()
|
||||
}
|
||||
|
||||
// Unset workers slice.
|
||||
p.workers = p.workers[:0]
|
||||
}
|
||||
|
||||
// FnWorker wraps a queue.SimpleQueue{} which
|
||||
// it feeds from to provide it with function
|
||||
// tasks to execute. It does so in a single
|
||||
// goroutine with state management utilities.
|
||||
type FnWorker struct {
|
||||
|
||||
// Queue is the fn queue that FnWorker
|
||||
// will feed from for upcoming tasks.
|
||||
Queue *queue.SimpleQueue[func(context.Context)]
|
||||
|
||||
// internal fields.
|
||||
service runners.Service
|
||||
}
|
||||
|
||||
// Start will attempt to start the Worker{}.
|
||||
func (w *FnWorker) Start() bool {
|
||||
return w.service.GoRun(w.run)
|
||||
}
|
||||
|
||||
// Stop will attempt to stop the Worker{}.
|
||||
func (w *FnWorker) Stop() bool {
|
||||
return w.service.Stop()
|
||||
}
|
||||
|
||||
// run wraps process to restart on any panic.
|
||||
func (w *FnWorker) run(ctx context.Context) {
|
||||
if w.Queue == nil {
|
||||
panic("not yet initialized")
|
||||
}
|
||||
log.Infof(ctx, "%p: starting worker", w)
|
||||
defer log.Infof(ctx, "%p: stopped worker", w)
|
||||
util.Must(func() { w.process(ctx) })
|
||||
}
|
||||
|
||||
// process is the main delivery worker processing routine.
|
||||
func (w *FnWorker) process(ctx context.Context) {
|
||||
if w.Queue == nil {
|
||||
// we perform this check here just
|
||||
// to ensure the compiler knows these
|
||||
// variables aren't nil in the loop,
|
||||
// even if already checked by caller.
|
||||
panic("not yet initialized")
|
||||
}
|
||||
|
||||
for {
|
||||
// Block until pop next func.
|
||||
fn, ok := w.Queue.PopCtx(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// run!
|
||||
fn(ctx)
|
||||
}
|
||||
}
|
157
internal/workers/worker_msg.go
Normal file
157
internal/workers/worker_msg.go
Normal file
|
@ -0,0 +1,157 @@
|
|||
// GoToSocial
|
||||
// Copyright (C) GoToSocial Authors admin@gotosocial.org
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package workers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"codeberg.org/gruf/go-runners"
|
||||
"codeberg.org/gruf/go-structr"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/queue"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
// MsgWorkerPool wraps multiple MsgWorker{}s in
|
||||
// a singular struct for easy multi start / stop.
|
||||
type MsgWorkerPool[Msg any] struct {
|
||||
|
||||
// Process handles queued message types.
|
||||
Process func(context.Context, Msg) error
|
||||
|
||||
// Queue is embedded queue.StructQueue{}
|
||||
// passed to each of the pool Worker{}s.
|
||||
Queue queue.StructQueue[Msg]
|
||||
|
||||
// internal fields.
|
||||
workers []*MsgWorker[Msg]
|
||||
}
|
||||
|
||||
// Init will initialize the worker pool queue with given struct indices.
|
||||
func (p *MsgWorkerPool[T]) Init(indices []structr.IndexConfig) {
|
||||
p.Queue.Init(structr.QueueConfig[T]{Indices: indices})
|
||||
}
|
||||
|
||||
// Start will attempt to start 'n' Worker{}s.
|
||||
func (p *MsgWorkerPool[T]) Start(n int) {
|
||||
// Check whether workers are
|
||||
// set (is already running).
|
||||
ok := (len(p.workers) > 0)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Allocate new msg workers slice.
|
||||
p.workers = make([]*MsgWorker[T], n)
|
||||
for i := range p.workers {
|
||||
|
||||
// Allocate new MsgWorker[T]{}.
|
||||
p.workers[i] = new(MsgWorker[T])
|
||||
p.workers[i].Process = p.Process
|
||||
p.workers[i].Queue = &p.Queue
|
||||
|
||||
// Attempt to start worker.
|
||||
// Return bool not useful
|
||||
// here, as true = started,
|
||||
// false = already running.
|
||||
_ = p.workers[i].Start()
|
||||
}
|
||||
}
|
||||
|
||||
// Stop will attempt to stop contained Worker{}s.
|
||||
func (p *MsgWorkerPool[T]) Stop() {
|
||||
// Check whether workers are
|
||||
// set (is currently running).
|
||||
ok := (len(p.workers) == 0)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Stop all running workers.
|
||||
for i := range p.workers {
|
||||
|
||||
// return bool not useful
|
||||
// here, as true = stopped,
|
||||
// false = never running.
|
||||
_ = p.workers[i].Stop()
|
||||
}
|
||||
|
||||
// Unset workers slice.
|
||||
p.workers = p.workers[:0]
|
||||
}
|
||||
|
||||
// MsgWorker wraps a processing function to
|
||||
// feed from a queue.StructQueue{} for messages
|
||||
// to process. It does so in a single goroutine
|
||||
// with state management utilities.
|
||||
type MsgWorker[Msg any] struct {
|
||||
|
||||
// Process handles queued message types.
|
||||
Process func(context.Context, Msg) error
|
||||
|
||||
// Queue is the Delivery{} message queue
|
||||
// that delivery worker will feed from.
|
||||
Queue *queue.StructQueue[Msg]
|
||||
|
||||
// internal fields.
|
||||
service runners.Service
|
||||
}
|
||||
|
||||
// Start will attempt to start the Worker{}.
|
||||
func (w *MsgWorker[T]) Start() bool {
|
||||
return w.service.GoRun(w.run)
|
||||
}
|
||||
|
||||
// Stop will attempt to stop the Worker{}.
|
||||
func (w *MsgWorker[T]) Stop() bool {
|
||||
return w.service.Stop()
|
||||
}
|
||||
|
||||
// run wraps process to restart on any panic.
|
||||
func (w *MsgWorker[T]) run(ctx context.Context) {
|
||||
if w.Process == nil || w.Queue == nil {
|
||||
panic("not yet initialized")
|
||||
}
|
||||
log.Infof(ctx, "%p: starting worker", w)
|
||||
defer log.Infof(ctx, "%p: stopped worker", w)
|
||||
util.Must(func() { w.process(ctx) })
|
||||
}
|
||||
|
||||
// process is the main delivery worker processing routine.
|
||||
func (w *MsgWorker[T]) process(ctx context.Context) {
|
||||
if w.Process == nil || w.Queue == nil {
|
||||
// we perform this check here just
|
||||
// to ensure the compiler knows these
|
||||
// variables aren't nil in the loop,
|
||||
// even if already checked by caller.
|
||||
panic("not yet initialized")
|
||||
}
|
||||
|
||||
for {
|
||||
// Block until pop next message.
|
||||
msg, ok := w.Queue.PopCtx(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Attempt to process popped message type.
|
||||
if err := w.Process(ctx, msg); err != nil {
|
||||
log.Errorf(ctx, "%p: error processing: %v", w, err)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,11 +18,8 @@
|
|||
package workers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"runtime"
|
||||
|
||||
"codeberg.org/gruf/go-runners"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/scheduler"
|
||||
|
@ -39,77 +36,49 @@ type Workers struct {
|
|||
// indexed queue of Delivery{} objects.
|
||||
Delivery delivery.WorkerPool
|
||||
|
||||
// ClientAPI provides a worker pool that handles both
|
||||
// incoming client actions, and our own side-effects.
|
||||
ClientAPI runners.WorkerPool
|
||||
// Client provides a worker pool that handles
|
||||
// incoming processing jobs from the client API.
|
||||
Client MsgWorkerPool[*messages.FromClientAPI]
|
||||
|
||||
// Federator provides a worker pool that handles both
|
||||
// incoming federated actions, and our own side-effects.
|
||||
Federator runners.WorkerPool
|
||||
// Federator provides a worker pool that handles
|
||||
// incoming processing jobs from the fedi API.
|
||||
Federator MsgWorkerPool[*messages.FromFediAPI]
|
||||
|
||||
// Enqueue functions for clientAPI / federator worker pools,
|
||||
// these are pointers to Processor{}.Enqueue___() msg functions.
|
||||
// This prevents dependency cycling as Processor depends on Workers.
|
||||
EnqueueClientAPI func(context.Context, ...messages.FromClientAPI)
|
||||
EnqueueFediAPI func(context.Context, ...messages.FromFediAPI)
|
||||
// Dereference provides a worker pool
|
||||
// for asynchronous dereferencer jobs.
|
||||
Dereference FnWorkerPool
|
||||
|
||||
// Blocking processing functions for clientAPI / federator.
|
||||
// These are pointers to Processor{}.Process___() msg functions.
|
||||
// This prevents dependency cycling as Processor depends on Workers.
|
||||
//
|
||||
// Rather than queueing messages for asynchronous processing, these
|
||||
// functions will process immediately and in a blocking manner, and
|
||||
// will not use up a worker slot.
|
||||
//
|
||||
// As such, you should only call them in special cases where something
|
||||
// synchronous needs to happen before you can do something else.
|
||||
ProcessFromClientAPI func(context.Context, messages.FromClientAPI) error
|
||||
ProcessFromFediAPI func(context.Context, messages.FromFediAPI) error
|
||||
|
||||
// Media manager worker pools.
|
||||
Media runners.WorkerPool
|
||||
// Media provides a worker pool for
|
||||
// asynchronous media processing jobs.
|
||||
Media FnWorkerPool
|
||||
|
||||
// prevent pass-by-value.
|
||||
_ nocopy
|
||||
}
|
||||
|
||||
// Start will start all of the contained
|
||||
// worker pools (and global scheduler).
|
||||
// StartScheduler starts the job scheduler.
|
||||
func (w *Workers) StartScheduler() {
|
||||
_ = w.Scheduler.Start() // false = already running
|
||||
}
|
||||
|
||||
// Start will start contained worker pools.
|
||||
func (w *Workers) Start() {
|
||||
// Get currently set GOMAXPROCS.
|
||||
maxprocs := runtime.GOMAXPROCS(0)
|
||||
|
||||
tryUntil("starting scheduler", 5, w.Scheduler.Start)
|
||||
|
||||
tryUntil("start delivery workerpool", 5, func() bool {
|
||||
n := config.GetAdvancedSenderMultiplier()
|
||||
if n < 1 {
|
||||
// clamp min senders to 1.
|
||||
return w.Delivery.Start(1)
|
||||
}
|
||||
return w.Delivery.Start(n * maxprocs)
|
||||
})
|
||||
|
||||
tryUntil("starting client API workerpool", 5, func() bool {
|
||||
return w.ClientAPI.Start(4*maxprocs, 400*maxprocs)
|
||||
})
|
||||
|
||||
tryUntil("starting federator workerpool", 5, func() bool {
|
||||
return w.Federator.Start(4*maxprocs, 400*maxprocs)
|
||||
})
|
||||
|
||||
tryUntil("starting media workerpool", 5, func() bool {
|
||||
return w.Media.Start(8*maxprocs, 80*maxprocs)
|
||||
})
|
||||
w.Delivery.Start(deliveryWorkers(maxprocs))
|
||||
w.Client.Start(4 * maxprocs)
|
||||
w.Federator.Start(4 * maxprocs)
|
||||
w.Dereference.Start(4 * maxprocs)
|
||||
w.Media.Start(8 * maxprocs)
|
||||
}
|
||||
|
||||
// Stop will stop all of the contained worker pools (and global scheduler).
|
||||
func (w *Workers) Stop() {
|
||||
tryUntil("stopping scheduler", 5, w.Scheduler.Stop)
|
||||
tryUntil("stopping delivery workerpool", 5, w.Delivery.Stop)
|
||||
tryUntil("stopping client API workerpool", 5, w.ClientAPI.Stop)
|
||||
tryUntil("stopping federator workerpool", 5, w.Federator.Stop)
|
||||
tryUntil("stopping media workerpool", 5, w.Media.Stop)
|
||||
_ = w.Scheduler.Stop() // false = not running
|
||||
w.Delivery.Stop()
|
||||
w.Client.Stop()
|
||||
w.Federator.Stop()
|
||||
w.Dereference.Stop()
|
||||
w.Media.Stop()
|
||||
}
|
||||
|
||||
// nocopy when embedded will signal linter to
|
||||
|
@ -120,12 +89,11 @@ func (*nocopy) Lock() {}
|
|||
|
||||
func (*nocopy) Unlock() {}
|
||||
|
||||
// tryUntil will attempt to call 'do' for 'count' attempts, before panicking with 'msg'.
|
||||
func tryUntil(msg string, count int, do func() bool) {
|
||||
for i := 0; i < count; i++ {
|
||||
if do() {
|
||||
return
|
||||
}
|
||||
func deliveryWorkers(maxprocs int) int {
|
||||
n := config.GetAdvancedSenderMultiplier()
|
||||
if n < 1 {
|
||||
// clamp to 1
|
||||
return 1
|
||||
}
|
||||
log.Panicf("failed %s after %d tries", msg, count)
|
||||
return n * maxprocs
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package testrig
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
|
@ -34,16 +35,8 @@ func InitTestConfig() {
|
|||
})
|
||||
}
|
||||
|
||||
func logLevel() string {
|
||||
level := "error"
|
||||
if lv := os.Getenv("GTS_LOG_LEVEL"); lv != "" {
|
||||
level = lv
|
||||
}
|
||||
return level
|
||||
}
|
||||
|
||||
var testDefaults = config.Configuration{
|
||||
LogLevel: logLevel(),
|
||||
LogLevel: cmp.Or(os.Getenv("GTS_LOG_LEVEL"), "error"),
|
||||
LogTimestampFormat: "02/01/2006 15:04:05.000",
|
||||
LogDbQueries: true,
|
||||
ApplicationName: "gotosocial",
|
||||
|
|
|
@ -24,6 +24,5 @@ import (
|
|||
|
||||
// NewTestMediaManager returns a media handler with the default test config, and the given db and storage.
|
||||
func NewTestMediaManager(state *state.State) *media.Manager {
|
||||
StartNoopWorkers(state) // ensure started
|
||||
return media.NewManager(state)
|
||||
}
|
||||
|
|
|
@ -31,10 +31,5 @@ import (
|
|||
// The passed in state will have its worker functions set appropriately,
|
||||
// but the state will not be initialized.
|
||||
func NewTestProcessor(state *state.State, federator *federation.Federator, emailSender email.Sender, mediaManager *media.Manager) *processing.Processor {
|
||||
p := processing.NewProcessor(cleaner.New(state), typeutils.NewConverter(state), federator, NewTestOauthServer(state.DB), mediaManager, state, emailSender)
|
||||
state.Workers.EnqueueClientAPI = p.Workers().EnqueueClientAPI
|
||||
state.Workers.EnqueueFediAPI = p.Workers().EnqueueFediAPI
|
||||
state.Workers.ProcessFromClientAPI = p.Workers().ProcessFromClientAPI
|
||||
state.Workers.ProcessFromFediAPI = p.Workers().ProcessFromFediAPI
|
||||
return p
|
||||
return processing.NewProcessor(cleaner.New(state), typeutils.NewConverter(state), federator, NewTestOauthServer(state.DB), mediaManager, state, emailSender)
|
||||
}
|
||||
|
|
|
@ -27,7 +27,10 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"codeberg.org/gruf/go-byteutil"
|
||||
"codeberg.org/gruf/go-kv/format"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/visibility"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||
tlprocessor "github.com/superseriousbusiness/gotosocial/internal/processing/timeline"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/processing/workers"
|
||||
|
@ -39,40 +42,55 @@ import (
|
|||
// Starts workers on the provided state using noop processing functions.
|
||||
// Useful when you *don't* want to trigger side effects in a test.
|
||||
func StartNoopWorkers(state *state.State) {
|
||||
state.Workers.EnqueueClientAPI = func(context.Context, ...messages.FromClientAPI) {}
|
||||
state.Workers.EnqueueFediAPI = func(context.Context, ...messages.FromFediAPI) {}
|
||||
state.Workers.ProcessFromClientAPI = func(context.Context, messages.FromClientAPI) error { return nil }
|
||||
state.Workers.ProcessFromFediAPI = func(context.Context, messages.FromFediAPI) error { return nil }
|
||||
state.Workers.Client.Process = func(ctx context.Context, msg *messages.FromClientAPI) error { return nil }
|
||||
state.Workers.Federator.Process = func(ctx context.Context, msg *messages.FromFediAPI) error { return nil }
|
||||
|
||||
state.Workers.Client.Init(messages.ClientMsgIndices())
|
||||
state.Workers.Federator.Init(messages.FederatorMsgIndices())
|
||||
state.Workers.Delivery.Init(nil)
|
||||
|
||||
// Specifically do NOT start the workers
|
||||
// as caller may require queue contents.
|
||||
// (i.e. don't want workers pulling)
|
||||
// _ = state.Workers.Client.Start(1)
|
||||
// _ = state.Workers.Federator.Start(1)
|
||||
// _ = state.Workers.Dereference.Start(1)
|
||||
// _ = state.Workers.Media.Start(1)
|
||||
//
|
||||
// (except for the scheduler, that's fine)
|
||||
_ = state.Workers.Scheduler.Start()
|
||||
_ = state.Workers.ClientAPI.Start(1, 10)
|
||||
_ = state.Workers.Federator.Start(1, 10)
|
||||
_ = state.Workers.Media.Start(1, 10)
|
||||
}
|
||||
|
||||
// Starts workers on the provided state using processing functions from the given
|
||||
// workers processor. Useful when you *do* want to trigger side effects in a test.
|
||||
func StartWorkers(state *state.State, processor *workers.Processor) {
|
||||
state.Workers.EnqueueClientAPI = processor.EnqueueClientAPI
|
||||
state.Workers.EnqueueFediAPI = processor.EnqueueFediAPI
|
||||
state.Workers.ProcessFromClientAPI = processor.ProcessFromClientAPI
|
||||
state.Workers.ProcessFromFediAPI = processor.ProcessFromFediAPI
|
||||
state.Workers.Client.Process = func(ctx context.Context, msg *messages.FromClientAPI) error {
|
||||
log.Debugf(ctx, "Workers{}.Client{}.Process(%s)", dump(msg))
|
||||
return processor.ProcessFromClientAPI(ctx, msg)
|
||||
}
|
||||
|
||||
state.Workers.Federator.Process = func(ctx context.Context, msg *messages.FromFediAPI) error {
|
||||
log.Debugf(ctx, "Workers{}.Federator{}.Process(%s)", dump(msg))
|
||||
return processor.ProcessFromFediAPI(ctx, msg)
|
||||
}
|
||||
|
||||
state.Workers.Client.Init(messages.ClientMsgIndices())
|
||||
state.Workers.Federator.Init(messages.FederatorMsgIndices())
|
||||
state.Workers.Delivery.Init(nil)
|
||||
|
||||
_ = state.Workers.Scheduler.Start()
|
||||
_ = state.Workers.ClientAPI.Start(1, 10)
|
||||
_ = state.Workers.Federator.Start(1, 10)
|
||||
_ = state.Workers.Media.Start(1, 10)
|
||||
state.Workers.Client.Start(1)
|
||||
state.Workers.Federator.Start(1)
|
||||
state.Workers.Dereference.Start(1)
|
||||
state.Workers.Media.Start(1)
|
||||
}
|
||||
|
||||
func StopWorkers(state *state.State) {
|
||||
_ = state.Workers.Scheduler.Stop()
|
||||
_ = state.Workers.ClientAPI.Stop()
|
||||
_ = state.Workers.Federator.Stop()
|
||||
_ = state.Workers.Media.Stop()
|
||||
state.Workers.Client.Stop()
|
||||
state.Workers.Federator.Stop()
|
||||
state.Workers.Dereference.Stop()
|
||||
state.Workers.Media.Stop()
|
||||
}
|
||||
|
||||
func StartTimelines(state *state.State, filter *visibility.Filter, converter *typeutils.Converter) {
|
||||
|
@ -241,3 +259,10 @@ func WaitFor(condition func() bool) bool {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dump returns debug output of 'v'.
|
||||
func dump(v any) string {
|
||||
var buf byteutil.Buffer
|
||||
format.Append(&buf, v)
|
||||
return buf.String()
|
||||
}
|
||||
|
|
9
vendor/codeberg.org/gruf/go-list/LICENSE
generated
vendored
Normal file
9
vendor/codeberg.org/gruf/go-list/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) gruf
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
3
vendor/codeberg.org/gruf/go-list/README.md
generated
vendored
Normal file
3
vendor/codeberg.org/gruf/go-list/README.md
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# go-list
|
||||
|
||||
a doubly-linked list library with generic support.
|
204
vendor/codeberg.org/gruf/go-list/list.go
generated
vendored
Normal file
204
vendor/codeberg.org/gruf/go-list/list.go
generated
vendored
Normal file
|
@ -0,0 +1,204 @@
|
|||
package list
|
||||
|
||||
// Elem represents an element in a doubly-linked list.
|
||||
type Elem[T any] struct {
|
||||
Next *Elem[T]
|
||||
Prev *Elem[T]
|
||||
Value T
|
||||
}
|
||||
|
||||
// List implements a doubly-linked list, where:
|
||||
// - Head = index 0 (i.e. the front)
|
||||
// - Tail = index n-1 (i.e. the back)
|
||||
type List[T any] struct {
|
||||
Head *Elem[T]
|
||||
Tail *Elem[T]
|
||||
len int
|
||||
}
|
||||
|
||||
// Len returns the current list length.
|
||||
func (l *List[T]) Len() int {
|
||||
return l.len
|
||||
}
|
||||
|
||||
// PushFront adds 'v' to the beginning of the list.
|
||||
func (l *List[T]) PushFront(v T) *Elem[T] {
|
||||
elem := &Elem[T]{Value: v}
|
||||
l.PushElemFront(elem)
|
||||
return elem
|
||||
}
|
||||
|
||||
// PushBack adds 'v' to the end of the list.
|
||||
func (l *List[T]) PushBack(v T) *Elem[T] {
|
||||
elem := &Elem[T]{Value: v}
|
||||
l.PushElemBack(elem)
|
||||
return elem
|
||||
}
|
||||
|
||||
// InsertBefore adds 'v' into the list before 'at'.
|
||||
func (l *List[T]) InsertBefore(v T, at *Elem[T]) *Elem[T] {
|
||||
elem := &Elem[T]{Value: v}
|
||||
l.InsertElemBefore(elem, at)
|
||||
return elem
|
||||
}
|
||||
|
||||
// InsertAfter adds 'v' into the list after 'at'.
|
||||
func (l *List[T]) InsertAfter(v T, at *Elem[T]) *Elem[T] {
|
||||
elem := &Elem[T]{Value: v}
|
||||
l.InsertElemAfter(elem, at)
|
||||
return elem
|
||||
}
|
||||
|
||||
// PushFrontNode adds 'elem' to the front of the list.
|
||||
func (l *List[T]) PushElemFront(elem *Elem[T]) {
|
||||
if elem == l.Head {
|
||||
return
|
||||
}
|
||||
|
||||
// Set new head.
|
||||
oldHead := l.Head
|
||||
l.Head = elem
|
||||
|
||||
if oldHead != nil {
|
||||
// Link to old head
|
||||
elem.Next = oldHead
|
||||
oldHead.Prev = elem
|
||||
} else {
|
||||
// First in list.
|
||||
l.Tail = elem
|
||||
}
|
||||
|
||||
// Incr count
|
||||
l.len++
|
||||
}
|
||||
|
||||
// PushBackNode adds 'elem' to the back of the list.
|
||||
func (l *List[T]) PushElemBack(elem *Elem[T]) {
|
||||
if elem == l.Tail {
|
||||
return
|
||||
}
|
||||
|
||||
// Set new tail.
|
||||
oldTail := l.Tail
|
||||
l.Tail = elem
|
||||
|
||||
if oldTail != nil {
|
||||
// Link to old tail
|
||||
elem.Prev = oldTail
|
||||
oldTail.Next = elem
|
||||
} else {
|
||||
// First in list.
|
||||
l.Head = elem
|
||||
}
|
||||
|
||||
// Incr count
|
||||
l.len++
|
||||
}
|
||||
|
||||
// InsertElemAfter adds 'elem' into the list after 'at' (i.e. at.Next = elem).
|
||||
func (l *List[T]) InsertElemAfter(elem *Elem[T], at *Elem[T]) {
|
||||
if elem == at {
|
||||
return
|
||||
}
|
||||
|
||||
// Set new 'next'.
|
||||
oldNext := at.Next
|
||||
at.Next = elem
|
||||
|
||||
// Link to 'at'.
|
||||
elem.Prev = at
|
||||
|
||||
if oldNext == nil {
|
||||
// Set new tail
|
||||
l.Tail = elem
|
||||
} else {
|
||||
// Link to 'prev'.
|
||||
oldNext.Prev = elem
|
||||
elem.Next = oldNext
|
||||
}
|
||||
|
||||
// Incr count
|
||||
l.len++
|
||||
}
|
||||
|
||||
// InsertElemBefore adds 'elem' into the list before 'at' (i.e. at.Prev = elem).
|
||||
func (l *List[T]) InsertElemBefore(elem *Elem[T], at *Elem[T]) {
|
||||
if elem == at {
|
||||
return
|
||||
}
|
||||
|
||||
// Set new 'prev'.
|
||||
oldPrev := at.Prev
|
||||
at.Prev = elem
|
||||
|
||||
// Link to 'at'.
|
||||
elem.Next = at
|
||||
|
||||
if oldPrev == nil {
|
||||
// Set new head
|
||||
l.Head = elem
|
||||
} else {
|
||||
// Link to 'next'.
|
||||
oldPrev.Next = elem
|
||||
elem.Prev = oldPrev
|
||||
}
|
||||
|
||||
// Incr count
|
||||
l.len++
|
||||
}
|
||||
|
||||
// Remove removes the 'elem' from the list.
|
||||
func (l *List[T]) Remove(elem *Elem[T]) {
|
||||
// Get linked elems.
|
||||
next := elem.Next
|
||||
prev := elem.Prev
|
||||
|
||||
// Unset elem.
|
||||
elem.Next = nil
|
||||
elem.Prev = nil
|
||||
|
||||
switch {
|
||||
// elem is ONLY one in list.
|
||||
case next == nil && prev == nil:
|
||||
l.Head = nil
|
||||
l.Tail = nil
|
||||
|
||||
// elem is front in list.
|
||||
case next != nil && prev == nil:
|
||||
l.Head = next
|
||||
next.Prev = nil
|
||||
|
||||
// elem is last in list.
|
||||
case prev != nil && next == nil:
|
||||
l.Tail = prev
|
||||
prev.Next = nil
|
||||
|
||||
// elem in middle of list.
|
||||
default:
|
||||
next.Prev = prev
|
||||
prev.Next = next
|
||||
}
|
||||
|
||||
// Decr count
|
||||
l.len--
|
||||
}
|
||||
|
||||
// Range calls 'fn' on every element from head forward in list.
|
||||
func (l *List[T]) Range(fn func(*Elem[T])) {
|
||||
if fn == nil {
|
||||
panic("nil function")
|
||||
}
|
||||
for elem := l.Head; elem != nil; elem = elem.Next {
|
||||
fn(elem)
|
||||
}
|
||||
}
|
||||
|
||||
// RangeReverse calls 'fn' on every element from tail backward in list.
|
||||
func (l *List[T]) RangeReverse(fn func(*Elem[T])) {
|
||||
if fn == nil {
|
||||
panic("nil function")
|
||||
}
|
||||
for elem := l.Tail; elem != nil; elem = elem.Prev {
|
||||
fn(elem)
|
||||
}
|
||||
}
|
61
vendor/codeberg.org/gruf/go-structr/cache.go
generated
vendored
61
vendor/codeberg.org/gruf/go-structr/cache.go
generated
vendored
|
@ -150,10 +150,10 @@ func (c *Cache[T]) Get(index *Index, keys ...Key) []T {
|
|||
|
||||
// Acquire lock.
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
// Check cache init.
|
||||
if c.copy == nil {
|
||||
c.mutex.Unlock()
|
||||
panic("not initialized")
|
||||
}
|
||||
|
||||
|
@ -173,9 +173,6 @@ func (c *Cache[T]) Get(index *Index, keys ...Key) []T {
|
|||
})
|
||||
}
|
||||
|
||||
// Done with lock.
|
||||
c.mutex.Unlock()
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
|
@ -185,12 +182,12 @@ func (c *Cache[T]) Put(values ...T) {
|
|||
// Acquire lock.
|
||||
c.mutex.Lock()
|
||||
|
||||
// Get func ptrs.
|
||||
invalid := c.invalid
|
||||
// Wrap unlock to only do once.
|
||||
unlock := once(c.mutex.Unlock)
|
||||
defer unlock()
|
||||
|
||||
// Check cache init.
|
||||
if c.copy == nil {
|
||||
c.mutex.Unlock()
|
||||
panic("not initialized")
|
||||
}
|
||||
|
||||
|
@ -203,8 +200,12 @@ func (c *Cache[T]) Put(values ...T) {
|
|||
)
|
||||
}
|
||||
|
||||
// Done with lock.
|
||||
c.mutex.Unlock()
|
||||
// Get func ptrs.
|
||||
invalid := c.invalid
|
||||
|
||||
// Done with
|
||||
// the lock.
|
||||
unlock()
|
||||
|
||||
if invalid != nil {
|
||||
// Pass all invalidated values
|
||||
|
@ -241,13 +242,13 @@ func (c *Cache[T]) LoadOne(index *Index, key Key, load func() (T, error)) (T, er
|
|||
// Acquire lock.
|
||||
c.mutex.Lock()
|
||||
|
||||
// Get func ptrs.
|
||||
ignore := c.ignore
|
||||
// Wrap unlock to only do once.
|
||||
unlock := once(c.mutex.Unlock)
|
||||
defer unlock()
|
||||
|
||||
// Check init'd.
|
||||
if c.copy == nil ||
|
||||
ignore == nil {
|
||||
c.mutex.Unlock()
|
||||
c.ignore == nil {
|
||||
panic("not initialized")
|
||||
}
|
||||
|
||||
|
@ -273,8 +274,12 @@ func (c *Cache[T]) LoadOne(index *Index, key Key, load func() (T, error)) (T, er
|
|||
}
|
||||
}
|
||||
|
||||
// Done with lock.
|
||||
c.mutex.Unlock()
|
||||
// Get func ptrs.
|
||||
ignore := c.ignore
|
||||
|
||||
// Done with
|
||||
// the lock.
|
||||
unlock()
|
||||
|
||||
if ok {
|
||||
// item found!
|
||||
|
@ -325,9 +330,12 @@ func (c *Cache[T]) Load(index *Index, keys []Key, load func([]Key) ([]T, error))
|
|||
// Acquire lock.
|
||||
c.mutex.Lock()
|
||||
|
||||
// Wrap unlock to only do once.
|
||||
unlock := once(c.mutex.Unlock)
|
||||
defer unlock()
|
||||
|
||||
// Check init'd.
|
||||
if c.copy == nil {
|
||||
c.mutex.Unlock()
|
||||
panic("not initialized")
|
||||
}
|
||||
|
||||
|
@ -365,8 +373,9 @@ func (c *Cache[T]) Load(index *Index, keys []Key, load func([]Key) ([]T, error))
|
|||
i++
|
||||
}
|
||||
|
||||
// Done with lock.
|
||||
c.mutex.Unlock()
|
||||
// Done with
|
||||
// the lock.
|
||||
unlock()
|
||||
|
||||
// Load uncached values.
|
||||
uncached, err := load(keys)
|
||||
|
@ -374,8 +383,20 @@ func (c *Cache[T]) Load(index *Index, keys []Key, load func([]Key) ([]T, error))
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Insert uncached.
|
||||
c.Put(uncached...)
|
||||
// Acquire lock.
|
||||
c.mutex.Lock()
|
||||
|
||||
// Store all uncached values.
|
||||
for i := range uncached {
|
||||
c.store_value(
|
||||
nil,
|
||||
Key{},
|
||||
uncached[i],
|
||||
)
|
||||
}
|
||||
|
||||
// Done with lock.
|
||||
c.mutex.Unlock()
|
||||
|
||||
// Append uncached to return values.
|
||||
values = append(values, uncached...)
|
||||
|
|
134
vendor/codeberg.org/gruf/go-structr/queue_ctx.go
generated
vendored
Normal file
134
vendor/codeberg.org/gruf/go-structr/queue_ctx.go
generated
vendored
Normal file
|
@ -0,0 +1,134 @@
|
|||
package structr
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// QueueCtx is a context-aware form of Queue{}.
|
||||
type QueueCtx[StructType any] struct {
|
||||
Queue[StructType]
|
||||
ch chan struct{}
|
||||
}
|
||||
|
||||
// PopFront pops the current value at front of the queue, else blocking on ctx.
|
||||
func (q *QueueCtx[T]) PopFront(ctx context.Context) (T, bool) {
|
||||
return q.pop(ctx, func() *list_elem {
|
||||
return q.queue.head
|
||||
})
|
||||
}
|
||||
|
||||
// PopBack pops the current value at back of the queue, else blocking on ctx.
|
||||
func (q *QueueCtx[T]) PopBack(ctx context.Context) (T, bool) {
|
||||
return q.pop(ctx, func() *list_elem {
|
||||
return q.queue.tail
|
||||
})
|
||||
}
|
||||
|
||||
// PushFront pushes values to front of queue.
|
||||
func (q *QueueCtx[T]) PushFront(values ...T) {
|
||||
q.mutex.Lock()
|
||||
for i := range values {
|
||||
item := q.index(values[i])
|
||||
q.queue.push_front(&item.elem)
|
||||
}
|
||||
if q.ch != nil {
|
||||
close(q.ch)
|
||||
q.ch = nil
|
||||
}
|
||||
q.mutex.Unlock()
|
||||
}
|
||||
|
||||
// PushBack pushes values to back of queue.
|
||||
func (q *QueueCtx[T]) PushBack(values ...T) {
|
||||
q.mutex.Lock()
|
||||
for i := range values {
|
||||
item := q.index(values[i])
|
||||
q.queue.push_back(&item.elem)
|
||||
}
|
||||
if q.ch != nil {
|
||||
close(q.ch)
|
||||
q.ch = nil
|
||||
}
|
||||
q.mutex.Unlock()
|
||||
}
|
||||
|
||||
// Wait returns a ptr to the current ctx channel,
|
||||
// this will block until next push to the queue.
|
||||
func (q *QueueCtx[T]) Wait() <-chan struct{} {
|
||||
q.mutex.Lock()
|
||||
if q.ch == nil {
|
||||
q.ch = make(chan struct{})
|
||||
}
|
||||
ctx := q.ch
|
||||
q.mutex.Unlock()
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (q *QueueCtx[T]) pop(ctx context.Context, next func() *list_elem) (T, bool) {
|
||||
if next == nil {
|
||||
panic("nil fn")
|
||||
} else if ctx == nil {
|
||||
panic("nil ctx")
|
||||
}
|
||||
|
||||
// Acquire lock.
|
||||
q.mutex.Lock()
|
||||
|
||||
var elem *list_elem
|
||||
|
||||
for {
|
||||
// Get element.
|
||||
elem = next()
|
||||
if elem != nil {
|
||||
break
|
||||
}
|
||||
|
||||
if q.ch == nil {
|
||||
// Allocate new ctx channel.
|
||||
q.ch = make(chan struct{})
|
||||
}
|
||||
|
||||
// Get current
|
||||
// ch pointer.
|
||||
ch := q.ch
|
||||
|
||||
// Unlock queue.
|
||||
q.mutex.Unlock()
|
||||
|
||||
select {
|
||||
// Ctx cancelled.
|
||||
case <-ctx.Done():
|
||||
var z T
|
||||
return z, false
|
||||
|
||||
// Pushed!
|
||||
case <-ch:
|
||||
}
|
||||
|
||||
// Relock queue.
|
||||
q.mutex.Lock()
|
||||
}
|
||||
|
||||
// Cast the indexed item from elem.
|
||||
item := (*indexed_item)(elem.data)
|
||||
|
||||
// Extract item value.
|
||||
value := item.data.(T)
|
||||
|
||||
// Delete queued.
|
||||
q.delete(item)
|
||||
|
||||
// Get func ptrs.
|
||||
pop := q.Queue.pop
|
||||
|
||||
// Done with lock.
|
||||
q.mutex.Unlock()
|
||||
|
||||
if pop != nil {
|
||||
// Pass to
|
||||
// user hook.
|
||||
pop(value)
|
||||
}
|
||||
|
||||
return value, true
|
||||
}
|
13
vendor/codeberg.org/gruf/go-structr/util.go
generated
vendored
Normal file
13
vendor/codeberg.org/gruf/go-structr/util.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
package structr
|
||||
|
||||
// once only executes 'fn' once.
|
||||
func once(fn func()) func() {
|
||||
var once int32
|
||||
return func() {
|
||||
if once != 0 {
|
||||
return
|
||||
}
|
||||
once = 1
|
||||
fn()
|
||||
}
|
||||
}
|
3
vendor/github.com/Masterminds/semver/v3/.golangci.yml
generated
vendored
3
vendor/github.com/Masterminds/semver/v3/.golangci.yml
generated
vendored
|
@ -5,12 +5,9 @@ linters:
|
|||
disable-all: true
|
||||
enable:
|
||||
- misspell
|
||||
- structcheck
|
||||
- govet
|
||||
- staticcheck
|
||||
- deadcode
|
||||
- errcheck
|
||||
- varcheck
|
||||
- unparam
|
||||
- ineffassign
|
||||
- nakedret
|
||||
|
|
17
vendor/github.com/Masterminds/semver/v3/Makefile
generated
vendored
17
vendor/github.com/Masterminds/semver/v3/Makefile
generated
vendored
|
@ -1,7 +1,5 @@
|
|||
GOPATH=$(shell go env GOPATH)
|
||||
GOLANGCI_LINT=$(GOPATH)/bin/golangci-lint
|
||||
GOFUZZBUILD = $(GOPATH)/bin/go-fuzz-build
|
||||
GOFUZZ = $(GOPATH)/bin/go-fuzz
|
||||
|
||||
.PHONY: lint
|
||||
lint: $(GOLANGCI_LINT)
|
||||
|
@ -19,19 +17,14 @@ test-cover:
|
|||
GO111MODULE=on go test -cover .
|
||||
|
||||
.PHONY: fuzz
|
||||
fuzz: $(GOFUZZBUILD) $(GOFUZZ)
|
||||
@echo "==> Fuzz testing"
|
||||
$(GOFUZZBUILD)
|
||||
$(GOFUZZ) -workdir=_fuzz
|
||||
fuzz:
|
||||
@echo "==> Running Fuzz Tests"
|
||||
go test -fuzz=FuzzNewVersion -fuzztime=15s .
|
||||
go test -fuzz=FuzzStrictNewVersion -fuzztime=15s .
|
||||
go test -fuzz=FuzzNewConstraint -fuzztime=15s .
|
||||
|
||||
$(GOLANGCI_LINT):
|
||||
# Install golangci-lint. The configuration for it is in the .golangci.yml
|
||||
# file in the root of the repository
|
||||
echo ${GOPATH}
|
||||
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.17.1
|
||||
|
||||
$(GOFUZZBUILD):
|
||||
cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||
|
||||
$(GOFUZZ):
|
||||
cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-dep
|
22
vendor/github.com/Masterminds/semver/v3/README.md
generated
vendored
22
vendor/github.com/Masterminds/semver/v3/README.md
generated
vendored
|
@ -18,18 +18,20 @@ If you are looking for a command line tool for version comparisons please see
|
|||
|
||||
## Package Versions
|
||||
|
||||
Note, import `github.com/github.com/Masterminds/semver/v3` to use the latest version.
|
||||
|
||||
There are three major versions fo the `semver` package.
|
||||
|
||||
* 3.x.x is the new stable and active version. This version is focused on constraint
|
||||
* 3.x.x is the stable and active version. This version is focused on constraint
|
||||
compatibility for range handling in other tools from other languages. It has
|
||||
a similar API to the v1 releases. The development of this version is on the master
|
||||
branch. The documentation for this version is below.
|
||||
* 2.x was developed primarily for [dep](https://github.com/golang/dep). There are
|
||||
no tagged releases and the development was performed by [@sdboyer](https://github.com/sdboyer).
|
||||
There are API breaking changes from v1. This version lives on the [2.x branch](https://github.com/Masterminds/semver/tree/2.x).
|
||||
* 1.x.x is the most widely used version with numerous tagged releases. This is the
|
||||
previous stable and is still maintained for bug fixes. The development, to fix
|
||||
bugs, occurs on the release-1 branch. You can read the documentation [here](https://github.com/Masterminds/semver/blob/release-1/README.md).
|
||||
* 1.x.x is the original release. It is no longer maintained. You should use the
|
||||
v3 release instead. You can read the documentation for the 1.x.x release
|
||||
[here](https://github.com/Masterminds/semver/blob/release-1/README.md).
|
||||
|
||||
## Parsing Semantic Versions
|
||||
|
||||
|
@ -242,3 +244,15 @@ for _, m := range msgs {
|
|||
|
||||
If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues)
|
||||
or [create a pull request](https://github.com/Masterminds/semver/pulls).
|
||||
|
||||
## Security
|
||||
|
||||
Security is an important consideration for this project. The project currently
|
||||
uses the following tools to help discover security issues:
|
||||
|
||||
* [CodeQL](https://github.com/Masterminds/semver)
|
||||
* [gosec](https://github.com/securego/gosec)
|
||||
* Daily Fuzz testing
|
||||
|
||||
If you believe you have found a security vulnerability you can privately disclose
|
||||
it through the [GitHub security page](https://github.com/Masterminds/semver/security).
|
||||
|
|
19
vendor/github.com/Masterminds/semver/v3/SECURITY.md
generated
vendored
Normal file
19
vendor/github.com/Masterminds/semver/v3/SECURITY.md
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
The following versions of semver are currently supported:
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 3.x | :white_check_mark: |
|
||||
| 2.x | :x: |
|
||||
| 1.x | :x: |
|
||||
|
||||
Fixes are only released for the latest minor version in the form of a patch release.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
You can privately disclose a vulnerability through GitHubs
|
||||
[private vulnerability reporting](https://github.com/Masterminds/semver/security/advisories)
|
||||
mechanism.
|
2
vendor/github.com/Masterminds/semver/v3/constraints.go
generated
vendored
2
vendor/github.com/Masterminds/semver/v3/constraints.go
generated
vendored
|
@ -586,7 +586,7 @@ func rewriteRange(i string) string {
|
|||
}
|
||||
o := i
|
||||
for _, v := range m {
|
||||
t := fmt.Sprintf(">= %s, <= %s", v[1], v[11])
|
||||
t := fmt.Sprintf(">= %s, <= %s ", v[1], v[11])
|
||||
o = strings.Replace(o, v[0], t, 1)
|
||||
}
|
||||
|
||||
|
|
22
vendor/github.com/Masterminds/semver/v3/fuzz.go
generated
vendored
22
vendor/github.com/Masterminds/semver/v3/fuzz.go
generated
vendored
|
@ -1,22 +0,0 @@
|
|||
// +build gofuzz
|
||||
|
||||
package semver
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
d := string(data)
|
||||
|
||||
// Test NewVersion
|
||||
_, _ = NewVersion(d)
|
||||
|
||||
// Test StrictNewVersion
|
||||
_, _ = StrictNewVersion(d)
|
||||
|
||||
// Test NewConstraint
|
||||
_, _ = NewConstraint(d)
|
||||
|
||||
// The return value should be 0 normally, 1 if the priority in future tests
|
||||
// should be increased, and -1 if future tests should skip passing in that
|
||||
// data. We do not have a reason to change priority so 0 is always returned.
|
||||
// There are example tests that do this.
|
||||
return 0
|
||||
}
|
6
vendor/github.com/felixge/httpsnoop/.travis.yml
generated
vendored
6
vendor/github.com/felixge/httpsnoop/.travis.yml
generated
vendored
|
@ -1,6 +0,0 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.6
|
||||
- 1.7
|
||||
- 1.8
|
2
vendor/github.com/felixge/httpsnoop/Makefile
generated
vendored
2
vendor/github.com/felixge/httpsnoop/Makefile
generated
vendored
|
@ -1,7 +1,7 @@
|
|||
.PHONY: ci generate clean
|
||||
|
||||
ci: clean generate
|
||||
go test -v ./...
|
||||
go test -race -v ./...
|
||||
|
||||
generate:
|
||||
go generate .
|
||||
|
|
4
vendor/github.com/felixge/httpsnoop/README.md
generated
vendored
4
vendor/github.com/felixge/httpsnoop/README.md
generated
vendored
|
@ -7,8 +7,8 @@ http.Handlers.
|
|||
Doing this requires non-trivial wrapping of the http.ResponseWriter interface,
|
||||
which is also exposed for users interested in a more low-level API.
|
||||
|
||||
[![GoDoc](https://godoc.org/github.com/felixge/httpsnoop?status.svg)](https://godoc.org/github.com/felixge/httpsnoop)
|
||||
[![Build Status](https://travis-ci.org/felixge/httpsnoop.svg?branch=master)](https://travis-ci.org/felixge/httpsnoop)
|
||||
[![Go Reference](https://pkg.go.dev/badge/github.com/felixge/httpsnoop.svg)](https://pkg.go.dev/github.com/felixge/httpsnoop)
|
||||
[![Build Status](https://github.com/felixge/httpsnoop/actions/workflows/main.yaml/badge.svg)](https://github.com/felixge/httpsnoop/actions/workflows/main.yaml)
|
||||
|
||||
## Usage Example
|
||||
|
||||
|
|
2
vendor/github.com/felixge/httpsnoop/capture_metrics.go
generated
vendored
2
vendor/github.com/felixge/httpsnoop/capture_metrics.go
generated
vendored
|
@ -52,7 +52,7 @@ func (m *Metrics) CaptureMetrics(w http.ResponseWriter, fn func(http.ResponseWri
|
|||
return func(code int) {
|
||||
next(code)
|
||||
|
||||
if !headerWritten {
|
||||
if !(code >= 100 && code <= 199) && !headerWritten {
|
||||
m.Code = code
|
||||
headerWritten = true
|
||||
}
|
||||
|
|
2
vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go
generated
vendored
2
vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go
generated
vendored
|
@ -1,5 +1,5 @@
|
|||
// +build go1.8
|
||||
// Code generated by "httpsnoop/codegen"; DO NOT EDIT
|
||||
// Code generated by "httpsnoop/codegen"; DO NOT EDIT.
|
||||
|
||||
package httpsnoop
|
||||
|
||||
|
|
2
vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go
generated
vendored
2
vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go
generated
vendored
|
@ -1,5 +1,5 @@
|
|||
// +build !go1.8
|
||||
// Code generated by "httpsnoop/codegen"; DO NOT EDIT
|
||||
// Code generated by "httpsnoop/codegen"; DO NOT EDIT.
|
||||
|
||||
package httpsnoop
|
||||
|
||||
|
|
53
vendor/github.com/go-openapi/analysis/.golangci.yml
generated
vendored
53
vendor/github.com/go-openapi/analysis/.golangci.yml
generated
vendored
|
@ -4,53 +4,58 @@ linters-settings:
|
|||
golint:
|
||||
min-confidence: 0
|
||||
gocyclo:
|
||||
min-complexity: 40
|
||||
gocognit:
|
||||
min-complexity: 40
|
||||
min-complexity: 45
|
||||
maligned:
|
||||
suggest-new: true
|
||||
dupl:
|
||||
threshold: 150
|
||||
threshold: 200
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 4
|
||||
min-occurrences: 3
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- maligned
|
||||
- unparam
|
||||
- lll
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
# scopelint is useful, but also reports false positives
|
||||
# that unfortunately can't be disabled. So we disable the
|
||||
# linter rather than changing code that works.
|
||||
# see: https://github.com/kyoh86/scopelint/issues/4
|
||||
- scopelint
|
||||
- gochecknoglobals
|
||||
- funlen
|
||||
- godox
|
||||
- gocognit
|
||||
#- whitespace
|
||||
- whitespace
|
||||
- wsl
|
||||
- funlen
|
||||
- testpackage
|
||||
- wrapcheck
|
||||
#- nlreturn
|
||||
- testpackage
|
||||
- nlreturn
|
||||
- gomnd
|
||||
- goerr113
|
||||
- exhaustivestruct
|
||||
#- errorlint
|
||||
#- nestif
|
||||
- gofumpt
|
||||
- goerr113
|
||||
- errorlint
|
||||
- nestif
|
||||
- godot
|
||||
- gci
|
||||
- dogsled
|
||||
- gofumpt
|
||||
- paralleltest
|
||||
- tparallel
|
||||
- thelper
|
||||
- ifshort
|
||||
- forbidigo
|
||||
- cyclop
|
||||
- varnamelen
|
||||
- exhaustruct
|
||||
- varnamelen
|
||||
- gci
|
||||
- depguard
|
||||
- errchkjson
|
||||
- inamedparam
|
||||
- nonamedreturns
|
||||
- musttag
|
||||
- ireturn
|
||||
- forcetypeassert
|
||||
- cyclop
|
||||
# deprecated linters
|
||||
- deadcode
|
||||
- interfacer
|
||||
- scopelint
|
||||
- varcheck
|
||||
- structcheck
|
||||
- golint
|
||||
- nosnakecase
|
||||
|
|
10
vendor/github.com/go-openapi/analysis/README.md
generated
vendored
10
vendor/github.com/go-openapi/analysis/README.md
generated
vendored
|
@ -1,8 +1,5 @@
|
|||
# OpenAPI initiative analysis
|
||||
# OpenAPI analysis [![Build Status](https://github.com/go-openapi/analysis/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/analysis/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/analysis/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/analysis)
|
||||
|
||||
[![Build Status](https://travis-ci.org/go-openapi/analysis.svg?branch=master)](https://travis-ci.org/go-openapi/analysis)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/x377t5o9ennm847o/branch/master?svg=true)](https://ci.appveyor.com/project/casualjim/go-openapi/analysis/branch/master)
|
||||
[![codecov](https://codecov.io/gh/go-openapi/analysis/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/analysis)
|
||||
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
|
||||
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/analysis/master/LICENSE)
|
||||
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/analysis.svg)](https://pkg.go.dev/github.com/go-openapi/analysis)
|
||||
|
@ -13,12 +10,12 @@ A foundational library to analyze an OAI specification document for easier reaso
|
|||
|
||||
## What's inside?
|
||||
|
||||
* A analyzer providing methods to walk the functional content of a specification
|
||||
* An analyzer providing methods to walk the functional content of a specification
|
||||
* A spec flattener producing a self-contained document bundle, while preserving `$ref`s
|
||||
* A spec merger ("mixin") to merge several spec documents into a primary spec
|
||||
* A spec "fixer" ensuring that response descriptions are non empty
|
||||
|
||||
[Documentation](https://godoc.org/github.com/go-openapi/analysis)
|
||||
[Documentation](https://pkg.go.dev/github.com/go-openapi/analysis)
|
||||
|
||||
## FAQ
|
||||
|
||||
|
@ -28,4 +25,3 @@ A foundational library to analyze an OAI specification document for easier reaso
|
|||
> This package currently only supports OpenAPI 2.0 (aka Swagger 2.0).
|
||||
> There is no plan to make it evolve toward supporting OpenAPI 3.x.
|
||||
> This [discussion thread](https://github.com/go-openapi/spec/issues/21) relates the full story.
|
||||
>
|
||||
|
|
32
vendor/github.com/go-openapi/analysis/appveyor.yml
generated
vendored
32
vendor/github.com/go-openapi/analysis/appveyor.yml
generated
vendored
|
@ -1,32 +0,0 @@
|
|||
version: "0.1.{build}"
|
||||
|
||||
clone_folder: C:\go-openapi\analysis
|
||||
shallow_clone: true # for startup speed
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
|
||||
#skip_tags: true
|
||||
#skip_branch_with_pr: true
|
||||
|
||||
# appveyor.yml
|
||||
build: off
|
||||
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
|
||||
stack: go 1.16
|
||||
|
||||
test_script:
|
||||
- go test -v -timeout 20m ./...
|
||||
|
||||
deploy: off
|
||||
|
||||
notifications:
|
||||
- provider: Slack
|
||||
incoming_webhook: https://hooks.slack.com/services/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
|
||||
auth_token:
|
||||
secure: Sf7kZf7ZGbnwWUMpffHwMu5A0cHkLK2MYY32LNTPj4+/3qC3Ghl7+9v4TSLOqOlCwdRNjOGblAq7s+GDJed6/xgRQl1JtCi1klzZNrYX4q01pgTPvvGcwbBkIYgeMaPeIRcK9OZnud7sRXdttozgTOpytps2U6Js32ip7uj5mHSg2ub0FwoSJwlS6dbezZ8+eDhoha0F/guY99BEwx8Bd+zROrT2TFGsSGOFGN6wFc7moCqTHO/YkWib13a2QNXqOxCCVBy/lt76Wp+JkeFppjHlzs/2lP3EAk13RIUAaesdEUHvIHrzCyNJEd3/+KO2DzsWOYfpktd+KBCvgaYOsoo7ubdT3IROeAegZdCgo/6xgCEsmFc9ZcqCfN5yNx2A+BZ2Vwmpws+bQ1E1+B5HDzzaiLcYfG4X2O210QVGVDLWsv1jqD+uPYeHY2WRfh5ZsIUFvaqgUEnwHwrK44/8REAhQavt1QAj5uJpsRd7CkRVPWRNK+yIky+wgbVUFEchRNmS55E7QWf+W4+4QZkQi7vUTMc9nbTUu2Es9NfvfudOpM2wZbn98fjpb/qq/nRv6Bk+ca+7XD5/IgNLMbWp2ouDdzbiHLCOfDUiHiDJhLfFZx9Bwo7ZwfzeOlbrQX66bx7xRKYmOe4DLrXhNcpbsMa8qbfxlZRCmYbubB/Y8h4=
|
||||
channel: bots
|
||||
on_build_success: false
|
||||
on_build_failure: true
|
||||
on_build_status_changed: true
|
10
vendor/github.com/go-openapi/analysis/doc.go
generated
vendored
10
vendor/github.com/go-openapi/analysis/doc.go
generated
vendored
|
@ -16,27 +16,27 @@
|
|||
Package analysis provides methods to work with a Swagger specification document from
|
||||
package go-openapi/spec.
|
||||
|
||||
Analyzing a specification
|
||||
## Analyzing a specification
|
||||
|
||||
An analysed specification object (type Spec) provides methods to work with swagger definition.
|
||||
|
||||
Flattening or expanding a specification
|
||||
## Flattening or expanding a specification
|
||||
|
||||
Flattening a specification bundles all remote $ref in the main spec document.
|
||||
Depending on flattening options, additional preprocessing may take place:
|
||||
- full flattening: replacing all inline complex constructs by a named entry in #/definitions
|
||||
- expand: replace all $ref's in the document by their expanded content
|
||||
|
||||
Merging several specifications
|
||||
## Merging several specifications
|
||||
|
||||
Mixin several specifications merges all Swagger constructs, and warns about found conflicts.
|
||||
|
||||
Fixing a specification
|
||||
## Fixing a specification
|
||||
|
||||
Unmarshalling a specification with golang json unmarshalling may lead to
|
||||
some unwanted result on present but empty fields.
|
||||
|
||||
Analyzing a Swagger schema
|
||||
## Analyzing a Swagger schema
|
||||
|
||||
Swagger schemas are analyzed to determine their complexity and qualify their content.
|
||||
*/
|
||||
|
|
64
vendor/github.com/go-openapi/analysis/flatten.go
generated
vendored
64
vendor/github.com/go-openapi/analysis/flatten.go
generated
vendored
|
@ -62,28 +62,26 @@ func newContext() *context {
|
|||
//
|
||||
// There is a minimal and a full flattening mode.
|
||||
//
|
||||
//
|
||||
// Minimally flattening a spec means:
|
||||
// - Expanding parameters, responses, path items, parameter items and header items (references to schemas are left
|
||||
// unscathed)
|
||||
// - Importing external (http, file) references so they become internal to the document
|
||||
// - Moving every JSON pointer to a $ref to a named definition (i.e. the reworked spec does not contain pointers
|
||||
// like "$ref": "#/definitions/myObject/allOfs/1")
|
||||
// - Expanding parameters, responses, path items, parameter items and header items (references to schemas are left
|
||||
// unscathed)
|
||||
// - Importing external (http, file) references so they become internal to the document
|
||||
// - Moving every JSON pointer to a $ref to a named definition (i.e. the reworked spec does not contain pointers
|
||||
// like "$ref": "#/definitions/myObject/allOfs/1")
|
||||
//
|
||||
// A minimally flattened spec thus guarantees the following properties:
|
||||
// - all $refs point to a local definition (i.e. '#/definitions/...')
|
||||
// - definitions are unique
|
||||
// - all $refs point to a local definition (i.e. '#/definitions/...')
|
||||
// - definitions are unique
|
||||
//
|
||||
// NOTE: arbitrary JSON pointers (other than $refs to top level definitions) are rewritten as definitions if they
|
||||
// represent a complex schema or express commonality in the spec.
|
||||
// Otherwise, they are simply expanded.
|
||||
// Self-referencing JSON pointers cannot resolve to a type and trigger an error.
|
||||
//
|
||||
//
|
||||
// Minimal flattening is necessary and sufficient for codegen rendering using go-swagger.
|
||||
//
|
||||
// Fully flattening a spec means:
|
||||
// - Moving every complex inline schema to be a definition with an auto-generated name in a depth-first fashion.
|
||||
// - Moving every complex inline schema to be a definition with an auto-generated name in a depth-first fashion.
|
||||
//
|
||||
// By complex, we mean every JSON object with some properties.
|
||||
// Arrays, when they do not define a tuple,
|
||||
|
@ -93,22 +91,21 @@ func newContext() *context {
|
|||
// have been created.
|
||||
//
|
||||
// Available flattening options:
|
||||
// - Minimal: stops flattening after minimal $ref processing, leaving schema constructs untouched
|
||||
// - Expand: expand all $ref's in the document (inoperant if Minimal set to true)
|
||||
// - Verbose: croaks about name conflicts detected
|
||||
// - RemoveUnused: removes unused parameters, responses and definitions after expansion/flattening
|
||||
// - Minimal: stops flattening after minimal $ref processing, leaving schema constructs untouched
|
||||
// - Expand: expand all $ref's in the document (inoperant if Minimal set to true)
|
||||
// - Verbose: croaks about name conflicts detected
|
||||
// - RemoveUnused: removes unused parameters, responses and definitions after expansion/flattening
|
||||
//
|
||||
// NOTE: expansion removes all $ref save circular $ref, which remain in place
|
||||
//
|
||||
// TODO: additional options
|
||||
// - ProgagateNameExtensions: ensure that created entries properly follow naming rules when their parent have set a
|
||||
// x-go-name extension
|
||||
// - LiftAllOfs:
|
||||
// - limit the flattening of allOf members when simple objects
|
||||
// - merge allOf with validation only
|
||||
// - merge allOf with extensions only
|
||||
// - ...
|
||||
//
|
||||
// - ProgagateNameExtensions: ensure that created entries properly follow naming rules when their parent have set a
|
||||
// x-go-name extension
|
||||
// - LiftAllOfs:
|
||||
// - limit the flattening of allOf members when simple objects
|
||||
// - merge allOf with validation only
|
||||
// - merge allOf with extensions only
|
||||
// - ...
|
||||
func Flatten(opts FlattenOpts) error {
|
||||
debugLog("FlattenOpts: %#v", opts)
|
||||
|
||||
|
@ -270,6 +267,12 @@ func nameInlinedSchemas(opts *FlattenOpts) error {
|
|||
}
|
||||
|
||||
func removeUnused(opts *FlattenOpts) {
|
||||
for removeUnusedSinglePass(opts) {
|
||||
// continue until no unused definition remains
|
||||
}
|
||||
}
|
||||
|
||||
func removeUnusedSinglePass(opts *FlattenOpts) (hasRemoved bool) {
|
||||
expected := make(map[string]struct{})
|
||||
for k := range opts.Swagger().Definitions {
|
||||
expected[path.Join(definitionsPath, jsonpointer.Escape(k))] = struct{}{}
|
||||
|
@ -280,6 +283,7 @@ func removeUnused(opts *FlattenOpts) {
|
|||
}
|
||||
|
||||
for k := range expected {
|
||||
hasRemoved = true
|
||||
debugLog("removing unused definition %s", path.Base(k))
|
||||
if opts.Verbose {
|
||||
log.Printf("info: removing unused definition: %s", path.Base(k))
|
||||
|
@ -288,6 +292,8 @@ func removeUnused(opts *FlattenOpts) {
|
|||
}
|
||||
|
||||
opts.Spec.reload() // re-analyze
|
||||
|
||||
return hasRemoved
|
||||
}
|
||||
|
||||
func importKnownRef(entry sortref.RefRevIdx, refStr, newName string, opts *FlattenOpts) error {
|
||||
|
@ -334,7 +340,7 @@ func importNewRef(entry sortref.RefRevIdx, refStr string, opts *FlattenOpts) err
|
|||
}
|
||||
|
||||
// generate a unique name - isOAIGen means that a naming conflict was resolved by changing the name
|
||||
newName, isOAIGen = uniqifyName(opts.Swagger().Definitions, nameFromRef(entry.Ref))
|
||||
newName, isOAIGen = uniqifyName(opts.Swagger().Definitions, nameFromRef(entry.Ref, opts))
|
||||
debugLog("new name for [%s]: %s - with name conflict:%t", strings.Join(entry.Keys, ", "), newName, isOAIGen)
|
||||
|
||||
opts.flattenContext.resolved[refStr] = newName
|
||||
|
@ -488,9 +494,9 @@ func stripPointersAndOAIGen(opts *FlattenOpts) error {
|
|||
// stripOAIGen strips the spec from unnecessary OAIGen constructs, initially created to dedupe flattened definitions.
|
||||
//
|
||||
// A dedupe is deemed unnecessary whenever:
|
||||
// - the only conflict is with its (single) parent: OAIGen is merged into its parent (reinlining)
|
||||
// - there is a conflict with multiple parents: merge OAIGen in first parent, the rewrite other parents to point to
|
||||
// the first parent.
|
||||
// - the only conflict is with its (single) parent: OAIGen is merged into its parent (reinlining)
|
||||
// - there is a conflict with multiple parents: merge OAIGen in first parent, the rewrite other parents to point to
|
||||
// the first parent.
|
||||
//
|
||||
// This function returns true whenever it re-inlined a complex schema, so the caller may chose to iterate
|
||||
// pointer and name resolution again.
|
||||
|
@ -652,6 +658,7 @@ func namePointers(opts *FlattenOpts) error {
|
|||
|
||||
refsToReplace := make(map[string]SchemaRef, len(opts.Spec.references.schemas))
|
||||
for k, ref := range opts.Spec.references.allRefs {
|
||||
debugLog("name pointers: %q => %#v", k, ref)
|
||||
if path.Dir(ref.String()) == definitionsPath {
|
||||
// this a ref to a top-level definition: ok
|
||||
continue
|
||||
|
@ -769,6 +776,10 @@ func flattenAnonPointer(key string, v SchemaRef, refsToReplace map[string]Schema
|
|||
|
||||
// identifying edge case when the namer did nothing because we point to a non-schema object
|
||||
// no definition is created and we expand the $ref for all callers
|
||||
debugLog("decide what to do with the schema pointed to: asch.IsSimpleSchema=%t, len(callers)=%d, parts.IsSharedParam=%t, parts.IsSharedResponse=%t",
|
||||
asch.IsSimpleSchema, len(callers), parts.IsSharedParam(), parts.IsSharedResponse(),
|
||||
)
|
||||
|
||||
if (!asch.IsSimpleSchema || len(callers) > 1) && !parts.IsSharedParam() && !parts.IsSharedResponse() {
|
||||
debugLog("replace JSON pointer at [%s] by definition: %s", key, v.Ref.String())
|
||||
if err := namer.Name(v.Ref.String(), v.Schema, asch); err != nil {
|
||||
|
@ -791,6 +802,7 @@ func flattenAnonPointer(key string, v SchemaRef, refsToReplace map[string]Schema
|
|||
return nil
|
||||
}
|
||||
|
||||
// everything that is a simple schema and not factorizable is expanded
|
||||
debugLog("expand JSON pointer for key=%s", key)
|
||||
|
||||
if err := replace.UpdateRefWithSchema(opts.Swagger(), key, v.Schema); err != nil {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue