Compare commits

...

27 commits

Author SHA1 Message Date
asonix 97567cf598 Prepare v0.3.113
All checks were successful
/ check (aarch64-unknown-linux-musl) (push) Successful in 3m26s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 3m34s
/ check (x86_64-unknown-linux-musl) (push) Successful in 3m40s
/ clippy (push) Successful in 1m40s
/ build (map[artifact:linux-amd64 platform:linux/amd64 target:x86_64-unknown-linux-musl]) (push) Successful in 6m22s
/ tests (push) Successful in 2m19s
/ publish-crate (push) Successful in 2m25s
/ build (map[artifact:linux-arm32v7 platform:linux/arm/v7 target:armv7-unknown-linux-musleabihf]) (push) Successful in 6m20s
/ publish-forgejo (push) Successful in 23s
/ publish-docker (push) Successful in 29s
/ build (map[artifact:linux-arm64v8 platform:linux/arm64 target:aarch64-unknown-linux-musl]) (push) Successful in 3m56s
2024-05-01 15:45:53 -05:00
asonix 4c663f399e Update dependencies (minor & point) 2024-05-01 15:43:53 -05:00
asonix 8a3256f52a Avoid deadlock of iterating over tree while transacting on that tree 2024-05-01 15:43:08 -05:00
asonix 13a2653fe8 Remove prerelease flag
All checks were successful
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 3m32s
/ clippy (push) Successful in 1m55s
/ tests (push) Successful in 2m43s
/ check (aarch64-unknown-linux-musl) (push) Successful in 3m22s
/ check (x86_64-unknown-linux-musl) (push) Successful in 3m45s
2024-04-23 14:00:04 -05:00
asonix 8dd9a86d22 Use match_pattern rather than path for metrics differentiation
All checks were successful
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 2m34s
/ check (x86_64-unknown-linux-musl) (push) Successful in 2m28s
/ check (aarch64-unknown-linux-musl) (push) Successful in 2m31s
/ clippy (push) Successful in 2m47s
/ tests (push) Successful in 3m10s
/ publish-docker (push) Successful in 14s
/ publish-forgejo (push) Successful in 20s
/ publish-crate (push) Successful in 2m27s
/ build (map[artifact:linux-arm64v8 platform:linux/arm64 target:aarch64-unknown-linux-musl]) (push) Successful in 4m21s
/ build (map[artifact:linux-amd64 platform:linux/amd64 target:x86_64-unknown-linux-musl]) (push) Successful in 5m37s
/ build (map[artifact:linux-arm32v7 platform:linux/arm/v7 target:armv7-unknown-linux-musleabihf]) (push) Successful in 5m27s
2024-04-21 11:44:16 -05:00
asonix 5c0c0591dd Prepare 0.3.112
All checks were successful
/ clippy (push) Successful in 1m24s
/ tests (push) Successful in 2m2s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 2m33s
/ check (x86_64-unknown-linux-musl) (push) Successful in 2m26s
/ check (aarch64-unknown-linux-musl) (push) Successful in 2m38s
2024-04-14 22:47:38 -05:00
asonix 04ca4e5401 Stable async-cpupool
All checks were successful
/ clippy (push) Successful in 2m18s
/ tests (push) Successful in 3m15s
/ check (aarch64-unknown-linux-musl) (push) Successful in 3m29s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 3m35s
/ check (x86_64-unknown-linux-musl) (push) Successful in 2m42s
2024-04-14 19:53:31 -05:00
asonix 1de1d76506 prerelease
All checks were successful
/ check (aarch64-unknown-linux-musl) (push) Successful in 3m22s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 3m39s
/ check (x86_64-unknown-linux-musl) (push) Successful in 3m7s
/ clippy (push) Successful in 1m30s
/ tests (push) Successful in 2m6s
/ build (map[artifact:linux-amd64 platform:linux/amd64 target:x86_64-unknown-linux-musl]) (push) Successful in 3m46s
/ publish-docker (push) Successful in 14s
/ publish-forgejo (push) Successful in 19s
/ publish-crate (push) Successful in 2m28s
/ build (map[artifact:linux-arm32v7 platform:linux/arm/v7 target:armv7-unknown-linux-musleabihf]) (push) Successful in 3m46s
/ build (map[artifact:linux-arm64v8 platform:linux/arm64 target:aarch64-unknown-linux-musl]) (push) Successful in 3m48s
2024-04-13 13:57:12 -05:00
asonix dd9225bb89 Prepare v0.3.111
All checks were successful
/ check (aarch64-unknown-linux-musl) (push) Successful in 3m33s
/ check (x86_64-unknown-linux-musl) (push) Successful in 3m52s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 3m37s
/ clippy (push) Successful in 1m41s
/ tests (push) Successful in 2m20s
/ publish-docker (push) Successful in 13s
/ publish-forgejo (push) Successful in 19s
/ publish-crate (push) Successful in 2m26s
/ build (map[artifact:linux-arm64v8 platform:linux/arm64 target:aarch64-unknown-linux-musl]) (push) Successful in 3m53s
/ build (map[artifact:linux-arm32v7 platform:linux/arm/v7 target:armv7-unknown-linux-musleabihf]) (push) Successful in 6m15s
/ build (map[artifact:linux-amd64 platform:linux/amd64 target:x86_64-unknown-linux-musl]) (push) Successful in 7m44s
2024-04-07 11:53:24 -05:00
asonix b577730836 Fix build
Some checks failed
/ clippy (push) Successful in 1m18s
/ check (aarch64-unknown-linux-musl) (push) Successful in 2m31s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 2m32s
/ tests (push) Successful in 2m2s
/ check (x86_64-unknown-linux-musl) (push) Has been cancelled
2024-04-07 11:40:57 -05:00
asonix 21883c168b BROKEN! Start collecting more metrics about various sizes 2024-04-07 11:04:03 -05:00
asonix 76a0c79369 Update base64, ammonia
All checks were successful
/ check (aarch64-unknown-linux-musl) (push) Successful in 2m32s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 2m31s
/ check (x86_64-unknown-linux-musl) (push) Successful in 3m28s
/ tests (push) Successful in 2m18s
/ publish-docker (push) Successful in 15s
/ clippy (push) Successful in 1m48s
/ build (map[artifact:linux-arm32v7 platform:linux/arm/v7 target:armv7-unknown-linux-musleabihf]) (push) Successful in 6m15s
/ publish-forgejo (push) Successful in 22s
/ publish-crate (push) Successful in 2m28s
/ build (map[artifact:linux-amd64 platform:linux/amd64 target:x86_64-unknown-linux-musl]) (push) Successful in 6m15s
/ build (map[artifact:linux-arm64v8 platform:linux/arm64 target:aarch64-unknown-linux-musl]) (push) Successful in 3m53s
2024-04-06 13:42:29 -05:00
asonix 6444782db9 Bump version, Update dependencies (minor & point) 2024-04-06 13:34:54 -05:00
asonix 14aea3256d Update dependencies (minor & point)
All checks were successful
/ clippy (push) Successful in 2m5s
/ tests (push) Successful in 3m15s
/ check (aarch64-unknown-linux-musl) (push) Successful in 3m40s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 5m14s
/ check (x86_64-unknown-linux-musl) (push) Successful in 3m46s
2024-03-23 19:10:13 -05:00
asonix f4f2aa2025 Update flake 2024-03-23 19:09:53 -05:00
asonix 615271fe80 Update opentelemetry dependencies, other dependencies minor & point
All checks were successful
/ clippy (push) Successful in 2m20s
/ tests (push) Successful in 3m10s
/ check (aarch64-unknown-linux-musl) (push) Successful in 3m38s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 3m29s
/ check (x86_64-unknown-linux-musl) (push) Successful in 3m32s
2024-03-10 20:09:16 -05:00
asonix 4aed601664 No console by default
All checks were successful
/ tests (push) Successful in 2m2s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 2m31s
/ check (x86_64-unknown-linux-musl) (push) Successful in 2m26s
/ clippy (push) Successful in 1m25s
/ check (aarch64-unknown-linux-musl) (push) Successful in 2m31s
2024-02-25 21:08:17 -06:00
asonix bf21f05aca Strip release binaries
All checks were successful
/ clippy (push) Successful in 2m22s
/ tests (push) Successful in 3m17s
/ check (aarch64-unknown-linux-musl) (push) Successful in 3m34s
/ check (x86_64-unknown-linux-musl) (push) Successful in 3m40s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 3m45s
2024-02-12 15:16:20 -06:00
asonix e69f6c6edb Remove prerelease marker
All checks were successful
/ tests (push) Successful in 3m4s
/ check (aarch64-unknown-linux-musl) (push) Successful in 3m26s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 3m36s
/ check (x86_64-unknown-linux-musl) (push) Successful in 3m39s
/ clippy (push) Successful in 2m12s
2024-02-12 14:32:46 -06:00
asonix 1e05eb4fe4 Bump version
Some checks failed
/ check (aarch64-unknown-linux-musl) (push) Successful in 3m26s
/ check (armv7-unknown-linux-musleabihf) (push) Successful in 3m34s
/ check (x86_64-unknown-linux-musl) (push) Successful in 3m17s
/ clippy (push) Successful in 2m12s
/ tests (push) Successful in 2m37s
/ publish-docker (push) Successful in 13s
/ publish-forgejo (push) Failing after 2m25s
/ publish-crate (push) Successful in 2m41s
/ build (map[artifact:linux-arm64v8 platform:linux/arm64 target:aarch64-unknown-linux-musl]) (push) Successful in 3m58s
/ build (map[artifact:linux-arm32v7 platform:linux/arm/v7 target:armv7-unknown-linux-musleabihf]) (push) Successful in 6m13s
/ build (map[artifact:linux-amd64 platform:linux/amd64 target:x86_64-unknown-linux-musl]) (push) Successful in 6m13s
2024-02-12 13:46:44 -06:00
asonix 7f09ac3edd Update dependencies (minor & point) 2024-02-12 13:42:45 -06:00
asonix 4788ad332a Update image version in docker-compose 2024-02-11 14:56:26 -06:00
asonix 1fd82915d3 Remove bad argument 2024-02-11 14:52:57 -06:00
asonix 0472082a97 Add actions, remove drone 2024-02-11 14:49:22 -06:00
asonix c8250acce7 Bump version
Some checks reported errors
continuous-integration/drone/push Build encountered an error
continuous-integration/drone/tag Build is passing
2024-02-05 00:25:15 -06:00
asonix b074759eb4 Update background-jobs, rework errors 2024-02-05 00:24:49 -06:00
asonix ed399f1531 Be more accurate for reqwest errors
All checks were successful
continuous-integration/drone/push Build is passing
2024-02-04 20:51:25 -06:00
34 changed files with 1114 additions and 1109 deletions

View file

@ -1,421 +0,0 @@
kind: pipeline
type: docker
name: clippy
platform:
arch: amd64
clone:
disable: true
steps:
- name: clone
image: alpine/git:latest
user: root
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- chown -R 991:991 .
- name: clippy
image: asonix/rust-builder:latest-linux-amd64
pull: always
commands:
- rustup component add clippy
- cargo clippy --no-deps -- -D warnings
trigger:
event:
- push
- pull_request
- tag
---
kind: pipeline
type: docker
name: tests
platform:
arch: amd64
clone:
disable: true
steps:
- name: clone
image: alpine/git:latest
user: root
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- chown -R 991:991 .
- name: tests
image: asonix/rust-builder:latest-linux-amd64
pull: always
commands:
- cargo test
trigger:
event:
- push
- pull_request
- tag
---
kind: pipeline
type: docker
name: check-amd64
platform:
arch: amd64
clone:
disable: true
steps:
- name: clone
image: alpine/git:latest
user: root
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- chown -R 991:991 .
- name: check
image: asonix/rust-builder:latest-linux-amd64
pull: always
commands:
- cargo check --target=$TARGET
trigger:
event:
- push
- pull_request
---
kind: pipeline
type: docker
name: build-amd64
platform:
arch: amd64
clone:
disable: true
steps:
- name: clone
image: alpine/git:latest
user: root
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- chown -R 991:991 .
- name: build
image: asonix/rust-builder:latest-linux-amd64
pull: always
commands:
- cargo build --target=$TARGET --release
- $TOOL-strip target/$TARGET/release/relay
- cp target/$TARGET/release/relay .
- cp relay relay-linux-amd64
- name: push
image: plugins/docker:20
settings:
username: asonix
password:
from_secret: dockerhub_token
repo: asonix/relay
dockerfile: docker/drone/Dockerfile
auto_tag: true
auto_tag_suffix: linux-amd64
build_args:
- REPO_ARCH=amd64
- name: publish
image: plugins/gitea-release:1
settings:
api_key:
from_secret: gitea_token
base_url: https://git.asonix.dog
files:
- relay-linux-amd64
depends_on:
- clippy
- tests
trigger:
event:
- tag
---
kind: pipeline
type: docker
name: check-arm64v8
platform:
arch: amd64
clone:
disable: true
steps:
- name: clone
image: alpine/git:latest
user: root
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- chown -R 991:991 .
- name: check
image: asonix/rust-builder:latest-linux-arm64v8
pull: always
commands:
- cargo check --target=$TARGET
trigger:
event:
- push
- pull_request
---
kind: pipeline
type: docker
name: build-arm64v8
platform:
arch: amd64
clone:
disable: true
steps:
- name: clone
image: alpine/git:latest
user: root
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- chown -R 991:991 .
- name: build
image: asonix/rust-builder:latest-linux-arm64v8
pull: always
commands:
- cargo build --target=$TARGET --release
- $TOOL-strip target/$TARGET/release/relay
- cp target/$TARGET/release/relay .
- cp relay relay-linux-arm64v8
- name: push
image: plugins/docker:20
settings:
username: asonix
password:
from_secret: dockerhub_token
repo: asonix/relay
dockerfile: docker/drone/Dockerfile
auto_tag: true
auto_tag_suffix: linux-arm64v8
build_args:
- REPO_ARCH=arm64v8
- name: publish
image: plugins/gitea-release:1
settings:
api_key:
from_secret: gitea_token
base_url: https://git.asonix.dog
files:
- relay-linux-arm64v8
depends_on:
- clippy
- tests
trigger:
event:
- tag
---
kind: pipeline
type: docker
name: check-arm32v7
platform:
arch: amd64
clone:
disable: true
steps:
- name: clone
image: alpine/git:latest
user: root
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- chown -R 991:991 .
- name: check
image: asonix/rust-builder:latest-linux-arm32v7
pull: always
commands:
- cargo check --target=$TARGET
trigger:
event:
- push
- pull_request
---
kind: pipeline
type: docker
name: build-arm32v7
platform:
arch: amd64
clone:
disable: true
steps:
- name: clone
image: alpine/git:latest
user: root
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- chown -R 991:991 .
- name: build
image: asonix/rust-builder:latest-linux-arm32v7
pull: always
commands:
- cargo build --target=$TARGET --release
- $TOOL-strip target/$TARGET/release/relay
- cp target/$TARGET/release/relay .
- cp relay relay-linux-arm32v7
- name: push
image: plugins/docker:20
settings:
username: asonix
password:
from_secret: dockerhub_token
repo: asonix/relay
dockerfile: docker/drone/Dockerfile
auto_tag: true
auto_tag_suffix: linux-arm32v7
build_args:
- REPO_ARCH=arm32v7
- name: publish
image: plugins/gitea-release:1
settings:
api_key:
from_secret: gitea_token
base_url: https://git.asonix.dog
files:
- relay-linux-arm32v7
depends_on:
- clippy
- tests
trigger:
event:
- tag
---
kind: pipeline
type: docker
name: manifest
platform:
arch: amd64
clone:
disable: true
steps:
- name: clone
image: alpine/git:latest
user: root
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- chown -R 991:991 .
- name: manifest
image: plugins/manifest:1
settings:
username: asonix
password:
from_secret: dockerhub_token
dump: true
auto_tag: true
ignore_missing: true
spec: docker/drone/manifest.tmpl
depends_on:
- build-amd64
- build-arm64v8
- build-arm32v7
trigger:
event:
- tag
---
kind: pipeline
type: docker
name: publish-crate
platform:
arch: amd64
clone:
disable: true
steps:
- name: clone
image: alpine/git:latest
user: root
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- chown -R 991:991 .
- name: publish
image: asonix/rust-builder:latest-linux-amd64
pull: always
environment:
CRATES_IO_TOKEN:
from_secret: crates_io_token
commands:
- cargo publish --token $CRATES_IO_TOKEN
depends_on:
- build-amd64
- build-arm64v8
- build-arm32v7
trigger:
event:
- tag

View file

@ -0,0 +1,61 @@
on:
push:
branches:
- '*'
pull_request:
branches:
- main
jobs:
clippy:
runs-on: docker
container:
image: docker.io/asonix/actions-base-image:0.1
steps:
-
name: Checkout relay
uses: https://github.com/actions/checkout@v4
-
name: Cargo Cache
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
-
name: Clippy
run: |
cargo clippy --no-default-features -- -D warnings
tests:
runs-on: docker
container:
image: docker.io/asonix/actions-base-image:0.1
steps:
-
name: Checkout relay
uses: https://github.com/actions/checkout@v4
-
name: Cargo Cache
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
-
name: Test
run: cargo test
check:
strategy:
fail-fast: false
matrix:
target:
- x86_64-unknown-linux-musl
- armv7-unknown-linux-musleabihf
- aarch64-unknown-linux-musl
runs-on: docker
container:
image: docker.io/asonix/actions-base-image:0.1
steps:
-
name: Checkout relay
uses: https://github.com/actions/checkout@v4
-
name: Cargo Cache
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
-
name: Debug builds
run: cargo zigbuild --target ${{ matrix.target }}

View file

@ -0,0 +1,225 @@
on:
push:
tags:
- 'v*.*.*'
env:
REGISTRY_IMAGE: asonix/relay
jobs:
clippy:
runs-on: base-image
container:
image: docker.io/asonix/actions-base-image:0.1
steps:
-
name: Checkout relay
uses: https://github.com/actions/checkout@v4
-
name: Cargo Cache
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
-
name: Clippy
run: |
cargo clippy --no-default-features -- -D warnings
tests:
runs-on: docker
container:
image: docker.io/asonix/actions-base-image:0.1
steps:
-
name: Checkout relay
uses: https://github.com/actions/checkout@v4
-
name: Cargo Cache
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
-
name: Test
run: cargo test
build:
needs:
- clippy
- tests
runs-on: docker
container:
image: docker.io/asonix/actions-base-image:0.1
strategy:
fail-fast: false
matrix:
info:
- target: x86_64-unknown-linux-musl
artifact: linux-amd64
platform: linux/amd64
- target: armv7-unknown-linux-musleabihf
artifact: linux-arm32v7
platform: linux/arm/v7
- target: aarch64-unknown-linux-musl
artifact: linux-arm64v8
platform: linux/arm64
steps:
-
name: Checkout relay
uses: https://github.com/actions/checkout@v4
-
name: Cargo Cache
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
-
name: Prepare Platform
run: |
platform=${{ matrix.info.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
shell: bash
-
name: Docker meta
id: meta
uses: https://github.com/docker/metadata-action@v5
with:
images: ${{ env.REGISTRY_IMAGE }}
flavor: |
latest=auto
suffix=-${{ matrix.info.artifact }}
tags: |
type=raw,value=latest,enable={{ is_default_branch }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
-
name: Set up QEMU
uses: https://github.com/docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: https://github.com/docker/setup-buildx-action@v3
-
name: Docker login
uses: https://github.com/docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Compile relay
run: cargo zigbuild --target ${{ matrix.info.target }} --release
-
name: Prepare artifacts
run: |
mkdir artifacts
cp target/${{ matrix.info.target }}/release/relay artifacts/relay-${{ matrix.info.artifact }}
-
uses: https://github.com/actions/upload-artifact@v3
with:
name: binaries
path: artifacts/
-
name: Prepare binary
run: |
cp target/${{ matrix.info.target }}/release/relay docker/forgejo/relay
-
name: Build and push ${{ matrix.info.platform }} docker image
id: build
uses: docker/build-push-action@v5
with:
context: ./docker/forgejo
platforms: ${{ matrix.info.platform }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},name-canonical=true,push=true
-
name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
echo "Created /tmp/digests/${digest#sha256:}"
shell: bash
-
name: Upload ${{ matrix.info.platform }} digest
uses: https://github.com/actions/upload-artifact@v3
with:
name: digests
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
publish-docker:
runs-on: docker
container:
image: docker.io/asonix/actions-base-image:0.1
needs: [build]
steps:
-
name: Download digests
uses: https://github.com/actions/download-artifact@v3
with:
name: digests
path: /tmp/digests
pattern: digests-*
merge-multiple: true
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Docker login
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Docker meta
id: meta
uses: https://github.com/docker/metadata-action@v5
with:
images: ${{ env.REGISTRY_IMAGE }}
flavor: |
latest=auto
tags: |
type=raw,value=latest,enable={{ is_default_branch }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
-
name: Create manifest list and push
working-directory: /tmp/digests
run: |
tags=$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "${DOCKER_METADATA_OUTPUT_JSON}")
images=$(printf "${{ env.REGISTRY_IMAGE }}@sha256:%s " *)
echo "Running 'docker buildx imagetools create ${tags[@]} ${images[@]}'"
docker buildx imagetools create ${tags[@]} ${images[@]}
shell: bash
-
name: Inspect Image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
publish-forgejo:
needs: [build]
runs-on: docker
container:
image: docker.io/asonix/actions-base-image:0.1
steps:
- uses: https://github.com/actions/download-artifact@v3
with:
name: binaries
path: artifacts/
merge-multiple: true
- uses: actions/forgejo-release@v1
with:
direction: upload
token: ${{ secrets.GITHUB_TOKEN }}
release-dir: artifacts/
publish-crate:
needs: [build]
runs-on: docker
container:
image: docker.io/asonix/actions-base-image:0.1
steps:
-
name: Checkout relay
uses: https://github.com/actions/checkout@v4
-
name: Cargo Cache
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
-
name: Publish Crate
run: cargo publish --token ${{ secrets.CRATES_IO_TOKEN }}

948
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
[package]
name = "ap-relay"
description = "A simple activitypub relay"
version = "0.3.107"
version = "0.3.113"
authors = ["asonix <asonix@asonix.dog>"]
license = "AGPL-3.0"
readme = "README.md"
@ -14,6 +14,9 @@ build = "src/build.rs"
name = "relay"
path = "src/main.rs"
[profile.release]
strip = true
[features]
console = ["dep:console-subscriber"]
default = []
@ -21,21 +24,20 @@ default = []
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0"
actix-web = { version = "4.4.0", default-features = false, features = ["compress-brotli", "compress-gzip", "rustls-0_22"] }
actix-webfinger = { version = "0.5.0", default-features = false }
activitystreams = "0.7.0-alpha.25"
activitystreams-ext = "0.1.0-alpha.3"
ammonia = "3.1.0"
async-cpupool = "0.2.0"
ammonia = "4.0.0"
async-cpupool = "0.2.2"
bcrypt = "0.15"
base64 = "0.21"
base64 = "0.22"
clap = { version = "4.0.0", features = ["derive"] }
color-eyre = "0.6.2"
config = { version = "0.14.0", default-features = false, features = ["toml", "json", "yaml"] }
console-subscriber = { version = "0.2", optional = true }
dashmap = "5.1.0"
dotenv = "0.15.0"
flume = "0.11.0"
lru = "0.12.0"
metrics = "0.22.0"
metrics-exporter-prometheus = { version = "0.13.0", default-features = false, features = [
@ -44,9 +46,9 @@ metrics-exporter-prometheus = { version = "0.13.0", default-features = false, fe
metrics-util = "0.16.0"
mime = "0.3.16"
minify-html = "0.15.0"
opentelemetry = "0.21"
opentelemetry_sdk = { version = "0.21", features = ["rt-tokio"] }
opentelemetry-otlp = "0.14"
opentelemetry = "0.22"
opentelemetry_sdk = { version = "0.22", features = ["rt-tokio"] }
opentelemetry-otlp = "0.15"
pin-project-lite = "0.2.9"
# pinned to metrics-util
quanta = "0.12.0"
@ -55,7 +57,7 @@ reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"
reqwest-middleware = "0.2"
reqwest-tracing = "0.4.5"
ring = "0.17.5"
rsa = { version = "0.9" }
rsa = "0.9"
rsa-magic-public-key = "0.8.0"
rustls = "0.22.0"
rustls-channel-resolver = "0.2.0"
@ -74,7 +76,7 @@ time = { version = "0.3.17", features = ["serde"] }
tracing = "0.1"
tracing-error = "0.2"
tracing-log = "0.2"
tracing-opentelemetry = "0.22"
tracing-opentelemetry = "0.23"
tracing-subscriber = { version = "0.3", features = [
"ansi",
"env-filter",
@ -84,7 +86,7 @@ tokio = { version = "1", features = ["full", "tracing"] }
uuid = { version = "1", features = ["v4", "serde"] }
[dependencies.background-jobs]
version = "0.17.0"
version = "0.18.0"
default-features = false
features = ["error-logging", "metrics", "tokio"]
@ -102,7 +104,7 @@ features = ["middleware", "ring"]
version = "0.7.9"
[build-dependencies]
anyhow = "1.0"
color-eyre = "0.6.2"
dotenv = "0.15.0"
ructe = { version = "0.17.0", features = ["sass", "mime03"] }
toml = "0.8.0"

View file

@ -1,11 +0,0 @@
ARG REPO_ARCH
FROM asonix/rust-runner:latest-linux-$REPO_ARCH
COPY relay /usr/local/bin/relay
USER app
EXPOSE 8080
VOLUME /mnt
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/usr/local/bin/relay"]

View file

@ -1,25 +0,0 @@
image: asonix/relay:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
{{/if}}
manifests:
-
image: asonix/relay:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
platform:
architecture: amd64
os: linux
-
image: asonix/relay:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64v8
platform:
architecture: arm64
os: linux
variant: v8
-
image: asonix/relay:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm32v7
platform:
architecture: arm
os: linux
variant: v7

24
docker/forgejo/Dockerfile Normal file
View file

@ -0,0 +1,24 @@
FROM alpine:3.19
ARG UID=991
ARG GID=991
ENV \
UID=${UID} \
GID=${GID}
USER root
RUN \
addgroup -g "${GID}" app && \
adduser -D -G app -u "${UID}" -g "" -h /opt/app app && \
apk add tini && \
chown -R app:app /mnt
COPY relay /usr/local/bin/relay
USER app
EXPOSE 6669
EXPOSE 8080
VOLUME /mnt
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/usr/local/bin/relay"]

View file

@ -2,7 +2,7 @@ version: '3.3'
services:
relay:
image: asonix/relay:0.3.85
image: asonix/relay:0.3.108
ports:
- "8079:8079"
restart: always

View file

@ -5,11 +5,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1705133751,
"narHash": "sha256-rCIsyE80jgiOU78gCWN3A0wE0tR2GI5nH6MlS+HaaSQ=",
"lastModified": 1711163522,
"narHash": "sha256-YN/Ciidm+A0fmJPWlHBGvVkcarYWSC+s3NTPk/P+q3c=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9b19f5e77dd906cb52dade0b7bd280339d2a1f3d",
"rev": "44d0940ea560dee511026a53f0e2e2cde489b4d4",
"type": "github"
},
"original": {

View file

@ -5,7 +5,7 @@
rustPlatform.buildRustPackage {
pname = "relay";
version = "0.3.107";
version = "0.3.113";
src = ./.;
cargoLock.lockFile = ./Cargo.lock;

View file

@ -21,7 +21,7 @@ fn git_info() {
}
}
fn version_info() -> Result<(), anyhow::Error> {
fn version_info() -> color_eyre::Result<()> {
let cargo_toml = Path::new(&std::env::var("CARGO_MANIFEST_DIR")?).join("Cargo.toml");
let mut file = File::open(cargo_toml)?;
@ -42,7 +42,7 @@ fn version_info() -> Result<(), anyhow::Error> {
Ok(())
}
fn main() -> Result<(), anyhow::Error> {
fn main() -> color_eyre::Result<()> {
dotenv::dotenv().ok();
git_info();

View file

@ -15,6 +15,10 @@ const MINUTES: u64 = 60 * SECONDS;
const HOURS: u64 = 60 * MINUTES;
const DAYS: u64 = 24 * HOURS;
pub(crate) fn recordable(len: usize) -> u32 {
((len as u64) % u64::from(u32::MAX)) as u32
}
type DistributionMap = BTreeMap<Vec<(String, String)>, Summary>;
#[derive(Clone)]
@ -299,7 +303,14 @@ impl Inner {
for sample in samples {
entry.add(*sample);
}
})
});
let mut total_len = 0;
for dist_map in d.values() {
total_len += dist_map.len();
}
metrics::gauge!("relay.collector.distributions.size").set(recordable(total_len));
}
let d = self.distributions.read().unwrap().clone();
@ -358,6 +369,7 @@ impl MemoryCollector {
) {
let mut d = self.inner.descriptions.write().unwrap();
d.entry(key.as_str().to_owned()).or_insert(description);
metrics::gauge!("relay.collector.descriptions.size").set(recordable(d.len()));
}
pub(crate) fn install(&self) -> Result<(), SetRecorderError<Self>> {

View file

@ -9,10 +9,10 @@ pub(crate) struct LastOnline {
impl LastOnline {
pub(crate) fn mark_seen(&self, iri: &IriStr) {
if let Some(authority) = iri.authority_str() {
self.domains
.lock()
.unwrap()
.insert(authority.to_string(), OffsetDateTime::now_utc());
let mut guard = self.domains.lock().unwrap();
guard.insert(authority.to_string(), OffsetDateTime::now_utc());
metrics::gauge!("relay.last-online.size",)
.set(crate::collector::recordable(guard.len()));
}
}

View file

@ -73,7 +73,9 @@ impl State {
}
pub(crate) fn cache(&self, object_id: IriString, actor_id: IriString) {
self.object_cache.write().unwrap().put(object_id, actor_id);
let mut guard = self.object_cache.write().unwrap();
guard.put(object_id, actor_id);
metrics::gauge!("relay.object-cache.size").set(crate::collector::recordable(guard.len()));
}
pub(crate) fn is_connected(&self, iri: &IriString) -> bool {

142
src/db.rs
View file

@ -7,7 +7,7 @@ use rsa::{
pkcs8::{DecodePrivateKey, EncodePrivateKey},
RsaPrivateKey,
};
use sled::{Batch, Tree};
use sled::{transaction::TransactionError, Batch, Transactional, Tree};
use std::{
collections::{BTreeMap, HashMap},
sync::{
@ -283,10 +283,15 @@ impl Db {
pub(crate) async fn check_health(&self) -> Result<(), Error> {
let next = self.inner.healthz_counter.fetch_add(1, Ordering::Relaxed);
self.unblock(move |inner| {
inner
let res = inner
.healthz
.insert("healthz", &next.to_be_bytes()[..])
.map_err(Error::from)
.map_err(Error::from);
metrics::gauge!("relay.db.healthz.size")
.set(crate::collector::recordable(inner.healthz.len()));
res
})
.await?;
self.inner.healthz.flush_async().await?;
@ -349,6 +354,9 @@ impl Db {
.actor_id_info
.insert(actor_id.as_str().as_bytes(), vec)?;
metrics::gauge!("relay.db.actor-id-info.size")
.set(crate::collector::recordable(inner.actor_id_info.len()));
Ok(())
})
.await
@ -383,6 +391,9 @@ impl Db {
.actor_id_instance
.insert(actor_id.as_str().as_bytes(), vec)?;
metrics::gauge!("relay.db.actor-id-instance.size")
.set(crate::collector::recordable(inner.actor_id_instance.len()));
Ok(())
})
.await
@ -417,6 +428,9 @@ impl Db {
.actor_id_contact
.insert(actor_id.as_str().as_bytes(), vec)?;
metrics::gauge!("relay.db.actor-id-contact.size")
.set(crate::collector::recordable(inner.actor_id_contact.len()));
Ok(())
})
.await
@ -447,6 +461,12 @@ impl Db {
inner
.media_url_media_id
.insert(url.as_str().as_bytes(), id.as_bytes())?;
metrics::gauge!("relay.db.media-id-media-url.size")
.set(crate::collector::recordable(inner.media_id_media_url.len()));
metrics::gauge!("relay.db.media-url-media-id.size")
.set(crate::collector::recordable(inner.media_url_media_id.len()));
Ok(())
})
.await
@ -538,6 +558,14 @@ impl Db {
inner
.actor_id_actor
.insert(actor.id.as_str().as_bytes(), vec)?;
metrics::gauge!("relay.db.public-key-actor-id.size").set(crate::collector::recordable(
inner.public_key_id_actor_id.len(),
));
metrics::gauge!("relay.db.actor-id-actor.size").set(crate::collector::recordable(
inner.public_key_id_actor_id.len(),
));
Ok(())
})
.await
@ -550,6 +578,10 @@ impl Db {
.connected_actor_ids
.remove(actor_id.as_str().as_bytes())?;
metrics::gauge!("relay.db.connected-actor-ids.size").set(crate::collector::recordable(
inner.connected_actor_ids.len(),
));
Ok(())
})
.await
@ -562,6 +594,10 @@ impl Db {
.connected_actor_ids
.insert(actor_id.as_str().as_bytes(), actor_id.as_str().as_bytes())?;
metrics::gauge!("relay.db.connected-actor-ids.size").set(crate::collector::recordable(
inner.connected_actor_ids.len(),
));
Ok(())
})
.await
@ -569,30 +605,64 @@ impl Db {
pub(crate) async fn add_blocks(&self, domains: Vec<String>) -> Result<(), Error> {
self.unblock(move |inner| {
for connected in inner.connected_by_domain(&domains) {
inner
.connected_actor_ids
.remove(connected.as_str().as_bytes())?;
}
let connected_by_domain = inner.connected_by_domain(&domains).collect::<Vec<_>>();
for authority in &domains {
inner
.blocked_domains
.insert(domain_key(authority), authority.as_bytes())?;
inner.allowed_domains.remove(domain_key(authority))?;
}
let res = (
&inner.connected_actor_ids,
&inner.blocked_domains,
&inner.allowed_domains,
)
.transaction(|(connected, blocked, allowed)| {
let mut connected_batch = Batch::default();
let mut blocked_batch = Batch::default();
let mut allowed_batch = Batch::default();
Ok(())
for connected in &connected_by_domain {
connected_batch.remove(connected.as_str().as_bytes());
}
for authority in &domains {
blocked_batch
.insert(domain_key(authority).as_bytes(), authority.as_bytes());
allowed_batch.remove(domain_key(authority).as_bytes());
}
connected.apply_batch(&connected_batch)?;
blocked.apply_batch(&blocked_batch)?;
allowed.apply_batch(&allowed_batch)?;
Ok(())
});
metrics::gauge!("relay.db.connected-actor-ids.size").set(crate::collector::recordable(
inner.connected_actor_ids.len(),
));
metrics::gauge!("relay.db.blocked-domains.size")
.set(crate::collector::recordable(inner.blocked_domains.len()));
metrics::gauge!("relay.db.allowed-domains.size")
.set(crate::collector::recordable(inner.allowed_domains.len()));
match res {
Ok(()) => Ok(()),
Err(TransactionError::Abort(e) | TransactionError::Storage(e)) => Err(e.into()),
}
})
.await
}
pub(crate) async fn remove_blocks(&self, domains: Vec<String>) -> Result<(), Error> {
self.unblock(move |inner| {
let mut blocked_batch = Batch::default();
for authority in &domains {
inner.blocked_domains.remove(domain_key(authority))?;
blocked_batch.remove(domain_key(authority).as_bytes());
}
inner.blocked_domains.apply_batch(blocked_batch)?;
metrics::gauge!("relay.db.blocked-domains.size")
.set(crate::collector::recordable(inner.blocked_domains.len()));
Ok(())
})
.await
@ -600,12 +670,17 @@ impl Db {
pub(crate) async fn add_allows(&self, domains: Vec<String>) -> Result<(), Error> {
self.unblock(move |inner| {
let mut allowed_batch = Batch::default();
for authority in &domains {
inner
.allowed_domains
.insert(domain_key(authority), authority.as_bytes())?;
allowed_batch.insert(domain_key(authority).as_bytes(), authority.as_bytes());
}
inner.allowed_domains.apply_batch(allowed_batch)?;
metrics::gauge!("relay.db.allowed-domains.size")
.set(crate::collector::recordable(inner.allowed_domains.len()));
Ok(())
})
.await
@ -614,17 +689,32 @@ impl Db {
pub(crate) async fn remove_allows(&self, domains: Vec<String>) -> Result<(), Error> {
self.unblock(move |inner| {
if inner.restricted_mode {
for connected in inner.connected_by_domain(&domains) {
inner
.connected_actor_ids
.remove(connected.as_str().as_bytes())?;
let connected_by_domain = inner.connected_by_domain(&domains).collect::<Vec<_>>();
let mut connected_batch = Batch::default();
for connected in &connected_by_domain {
connected_batch.remove(connected.as_str().as_bytes());
}
inner.connected_actor_ids.apply_batch(connected_batch)?;
metrics::gauge!("relay.db.connected-actor-ids.size").set(
crate::collector::recordable(inner.connected_actor_ids.len()),
);
}
let mut allowed_batch = Batch::default();
for authority in &domains {
inner.allowed_domains.remove(domain_key(authority))?;
allowed_batch.remove(domain_key(authority).as_bytes());
}
inner.allowed_domains.apply_batch(allowed_batch)?;
metrics::gauge!("relay.db.allowed-domains.size")
.set(crate::collector::recordable(inner.allowed_domains.len()));
Ok(())
})
.await
@ -665,6 +755,10 @@ impl Db {
inner
.settings
.insert("private-key".as_bytes(), pem_pkcs8.as_bytes())?;
metrics::gauge!("relay.db.settings.size")
.set(crate::collector::recordable(inner.settings.len()));
Ok(())
})
.await

View file

@ -4,54 +4,82 @@ use actix_web::{
http::StatusCode,
HttpResponse,
};
use background_jobs::BoxError;
use color_eyre::eyre::Error as Report;
use http_signature_normalization_reqwest::SignError;
use std::{convert::Infallible, fmt::Debug, io};
use std::{convert::Infallible, io, sync::Arc};
use tokio::task::JoinError;
use tracing_error::SpanTrace;
#[derive(Clone)]
struct ArcKind {
kind: Arc<ErrorKind>,
}
impl std::fmt::Debug for ArcKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.kind.fmt(f)
}
}
impl std::fmt::Display for ArcKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.kind.fmt(f)
}
}
impl std::error::Error for ArcKind {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.kind.source()
}
}
pub(crate) struct Error {
context: String,
kind: ErrorKind,
kind: ArcKind,
display: Box<str>,
debug: Box<str>,
}
impl Error {
fn kind(&self) -> &ErrorKind {
&self.kind.kind
}
pub(crate) fn is_breaker(&self) -> bool {
matches!(self.kind, ErrorKind::Breaker)
matches!(self.kind(), ErrorKind::Breaker)
}
pub(crate) fn is_not_found(&self) -> bool {
matches!(self.kind, ErrorKind::Status(_, StatusCode::NOT_FOUND))
matches!(self.kind(), ErrorKind::Status(_, StatusCode::NOT_FOUND))
}
pub(crate) fn is_bad_request(&self) -> bool {
matches!(self.kind, ErrorKind::Status(_, StatusCode::BAD_REQUEST))
matches!(self.kind(), ErrorKind::Status(_, StatusCode::BAD_REQUEST))
}
pub(crate) fn is_gone(&self) -> bool {
matches!(self.kind, ErrorKind::Status(_, StatusCode::GONE))
matches!(self.kind(), ErrorKind::Status(_, StatusCode::GONE))
}
pub(crate) fn is_malformed_json(&self) -> bool {
matches!(self.kind, ErrorKind::Json(_))
matches!(self.kind(), ErrorKind::Json(_))
}
}
impl std::fmt::Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{:?}", self.kind)
f.write_str(&self.debug)
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{}", self.kind)?;
std::fmt::Display::fmt(&self.context, f)
f.write_str(&self.display)
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.kind.source()
self.kind().source()
}
}
@ -60,25 +88,36 @@ where
ErrorKind: From<T>,
{
fn from(error: T) -> Self {
let kind = ArcKind {
kind: Arc::new(ErrorKind::from(error)),
};
let report = Report::new(kind.clone());
let display = format!("{report}");
let debug = format!("{report:?}");
Error {
context: SpanTrace::capture().to_string(),
kind: error.into(),
kind,
display: Box::from(display),
debug: Box::from(debug),
}
}
}
#[derive(Debug, thiserror::Error)]
pub(crate) enum ErrorKind {
#[error("Error queueing job, {0}")]
Queue(anyhow::Error),
#[error("Error in extractor")]
Extractor(#[from] crate::extractors::ErrorKind),
#[error("Error in configuration, {0}")]
#[error("Error queueing job")]
Queue(#[from] BoxError),
#[error("Error in configuration")]
Config(#[from] config::ConfigError),
#[error("Couldn't parse key, {0}")]
#[error("Couldn't parse key")]
Pkcs8(#[from] rsa::pkcs8::Error),
#[error("Couldn't encode public key, {0}")]
#[error("Couldn't encode public key")]
Spki(#[from] rsa::pkcs8::spki::Error),
#[error("Couldn't sign request")]
@ -87,28 +126,28 @@ pub(crate) enum ErrorKind {
#[error("Couldn't make request")]
Reqwest(#[from] reqwest::Error),
#[error("Couldn't build client")]
#[error("Couldn't make request")]
ReqwestMiddleware(#[from] reqwest_middleware::Error),
#[error("Couldn't parse IRI, {0}")]
#[error("Couldn't parse IRI")]
ParseIri(#[from] activitystreams::iri_string::validate::Error),
#[error("Couldn't normalize IRI, {0}")]
#[error("Couldn't normalize IRI")]
NormalizeIri(#[from] std::collections::TryReserveError),
#[error("Couldn't perform IO, {0}")]
#[error("Couldn't perform IO")]
Io(#[from] io::Error),
#[error("Couldn't sign string, {0}")]
Rsa(rsa::errors::Error),
#[error("Couldn't use db, {0}")]
#[error("Couldn't use db")]
Sled(#[from] sled::Error),
#[error("Couldn't do the json thing, {0}")]
#[error("Couldn't do the json thing")]
Json(#[from] serde_json::Error),
#[error("Couldn't sign request, {0}")]
#[error("Couldn't sign request")]
Sign(#[from] SignError),
#[error("Couldn't sign digest")]
@ -147,10 +186,10 @@ pub(crate) enum ErrorKind {
#[error("Wrong ActivityPub kind, {0}")]
Kind(String),
#[error("Too many CPUs, {0}")]
#[error("Too many CPUs")]
CpuCount(#[from] std::num::TryFromIntError),
#[error("{0}")]
#[error("Host mismatch")]
HostMismatch(#[from] CheckError),
#[error("Couldn't flush buffer")]
@ -204,7 +243,7 @@ pub(crate) enum ErrorKind {
impl ResponseError for Error {
fn status_code(&self) -> StatusCode {
match self.kind {
match self.kind() {
ErrorKind::NotAllowed(_) | ErrorKind::WrongActor(_) | ErrorKind::BadActor(_, _) => {
StatusCode::FORBIDDEN
}
@ -224,7 +263,7 @@ impl ResponseError for Error {
.insert_header(("Content-Type", "application/activity+json"))
.body(
serde_json::to_string(&serde_json::json!({
"error": self.kind.to_string(),
"error": self.kind().to_string(),
}))
.unwrap_or_else(|_| "{}".to_string()),
)

View file

@ -1,19 +1,15 @@
use actix_web::{
dev::Payload,
error::ParseError,
http::{
header::{from_one_raw_str, Header, HeaderName, HeaderValue, TryIntoHeaderValue},
StatusCode,
},
http::header::{from_one_raw_str, Header, HeaderName, HeaderValue, TryIntoHeaderValue},
web::Data,
FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError,
FromRequest, HttpMessage, HttpRequest,
};
use bcrypt::{BcryptError, DEFAULT_COST};
use http_signature_normalization_actix::{prelude::InvalidHeaderValue, Canceled, Spawn};
use std::{convert::Infallible, str::FromStr, time::Instant};
use tracing_error::SpanTrace;
use crate::{db::Db, future::LocalBoxFuture, spawner::Spawner};
use crate::{db::Db, error::Error, future::LocalBoxFuture, spawner::Spawner};
#[derive(Clone)]
pub(crate) struct AdminConfig {
@ -83,74 +79,42 @@ impl Admin {
}
}
#[derive(Debug, thiserror::Error)]
#[error("Failed authentication")]
pub(crate) struct Error {
context: String,
#[source]
kind: ErrorKind,
}
impl Error {
fn invalid() -> Self {
Error {
context: SpanTrace::capture().to_string(),
kind: ErrorKind::Invalid,
}
Error::from(ErrorKind::Invalid)
}
fn missing_config() -> Self {
Error {
context: SpanTrace::capture().to_string(),
kind: ErrorKind::MissingConfig,
}
Error::from(ErrorKind::MissingConfig)
}
fn missing_db() -> Self {
Error {
context: SpanTrace::capture().to_string(),
kind: ErrorKind::MissingDb,
}
Error::from(ErrorKind::MissingDb)
}
fn missing_spawner() -> Self {
Error {
context: SpanTrace::capture().to_string(),
kind: ErrorKind::MissingSpawner,
}
Error::from(ErrorKind::MissingSpawner)
}
fn bcrypt_verify(e: BcryptError) -> Self {
Error {
context: SpanTrace::capture().to_string(),
kind: ErrorKind::BCryptVerify(e),
}
Error::from(ErrorKind::BCryptVerify(e))
}
fn bcrypt_hash(e: BcryptError) -> Self {
Error {
context: SpanTrace::capture().to_string(),
kind: ErrorKind::BCryptHash(e),
}
Error::from(ErrorKind::BCryptHash(e))
}
fn parse_header(e: ParseError) -> Self {
Error {
context: SpanTrace::capture().to_string(),
kind: ErrorKind::ParseHeader(e),
}
Error::from(ErrorKind::ParseHeader(e))
}
fn canceled(_: Canceled) -> Self {
Error {
context: SpanTrace::capture().to_string(),
kind: ErrorKind::Canceled,
}
Error::from(ErrorKind::Canceled)
}
}
#[derive(Debug, thiserror::Error)]
enum ErrorKind {
pub(crate) enum ErrorKind {
#[error("Invalid API Token")]
Invalid,
@ -176,20 +140,6 @@ enum ErrorKind {
ParseHeader(#[source] ParseError),
}
impl ResponseError for Error {
fn status_code(&self) -> StatusCode {
match self.kind {
ErrorKind::Invalid | ErrorKind::ParseHeader(_) => StatusCode::BAD_REQUEST,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
fn error_response(&self) -> HttpResponse {
HttpResponse::build(self.status_code())
.json(serde_json::json!({ "msg": self.kind.to_string() }))
}
}
impl FromRequest for Admin {
type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self, Self::Error>>;

View file

@ -40,7 +40,12 @@ fn debug_object(activity: &serde_json::Value) -> &serde_json::Value {
object
}
pub(crate) fn build_storage() -> MetricsStorage<Storage<TokioTimer>> {
MetricsStorage::wrap(Storage::new(TokioTimer))
}
pub(crate) fn create_workers(
storage: MetricsStorage<Storage<TokioTimer>>,
state: State,
actors: ActorCache,
media: MediaCache,
@ -48,18 +53,15 @@ pub(crate) fn create_workers(
) -> std::io::Result<JobServer> {
let deliver_concurrency = config.deliver_concurrency();
let queue_handle = WorkerConfig::new(
MetricsStorage::wrap(Storage::new(TokioTimer)),
move |queue_handle| {
JobState::new(
state.clone(),
actors.clone(),
JobServer::new(queue_handle),
media.clone(),
config.clone(),
)
},
)
let queue_handle = WorkerConfig::new(storage, move |queue_handle| {
JobState::new(
state.clone(),
actors.clone(),
JobServer::new(queue_handle),
media.clone(),
config.clone(),
)
})
.register::<Deliver>()
.register::<DeliverMany>()
.register::<QueryNodeinfo>()

View file

@ -64,12 +64,13 @@ fn generate_announce(
impl Job for Announce {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::apub::Announce";
const QUEUE: &'static str = "apub";
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -113,12 +113,13 @@ fn generate_accept_follow(
impl Job for Follow {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::apub::Follow";
const QUEUE: &'static str = "apub";
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -49,12 +49,13 @@ impl Forward {
impl Job for Forward {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::apub::Forward";
const QUEUE: &'static str = "apub";
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -35,12 +35,13 @@ impl Reject {
impl Job for Reject {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::apub::Reject";
const QUEUE: &'static str = "apub";
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -50,12 +50,13 @@ impl Undo {
impl Job for Undo {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::apub::Undo";
const QUEUE: &'static str = "apub";
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -87,13 +87,14 @@ fn to_contact(contact: AcceptedActors) -> Option<(String, String, IriString, Iri
impl Job for QueryContact {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::QueryContact";
const QUEUE: &'static str = "maintenance";
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -35,7 +35,7 @@ impl Deliver {
}
#[tracing::instrument(name = "Deliver", skip(state))]
async fn permform(self, state: JobState) -> Result<(), Error> {
async fn perform(self, state: JobState) -> Result<(), Error> {
if let Err(e) = state
.state
.requests
@ -58,13 +58,14 @@ impl Deliver {
impl Job for Deliver {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::Deliver";
const QUEUE: &'static str = "deliver";
const BACKOFF: Backoff = Backoff::Exponential(8);
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.permform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -47,12 +47,13 @@ impl DeliverMany {
impl Job for DeliverMany {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::DeliverMany";
const QUEUE: &'static str = "deliver";
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -167,13 +167,14 @@ impl QueryInstance {
impl Job for QueryInstance {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::QueryInstance";
const QUEUE: &'static str = "maintenance";
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -106,13 +106,14 @@ impl QueryNodeinfo {
impl Job for QueryNodeinfo {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::QueryNodeinfo";
const QUEUE: &'static str = "maintenance";
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -25,12 +25,13 @@ impl Listeners {
impl Job for Listeners {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::Listeners";
const QUEUE: &'static str = "maintenance";
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -15,13 +15,14 @@ impl RecordLastOnline {
impl Job for RecordLastOnline {
type State = JobState;
type Future = BoxFuture<'static, anyhow::Result<()>>;
type Error = Error;
type Future = BoxFuture<'static, Result<(), Self::Error>>;
const NAME: &'static str = "relay::jobs::RecordLastOnline";
const QUEUE: &'static str = "maintenance";
const BACKOFF: Backoff = Backoff::Linear(1);
fn run(self, state: Self::State) -> Self::Future {
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
Box::pin(self.perform(state))
}
}

View file

@ -56,8 +56,9 @@ use self::{
fn init_subscriber(
software_name: &'static str,
opentelemetry_url: Option<&IriString>,
) -> Result<(), anyhow::Error> {
) -> color_eyre::Result<()> {
LogTracer::init()?;
color_eyre::install()?;
let targets: Targets = std::env::var("RUST_LOG")
.unwrap_or_else(|_| "info".into())
@ -140,7 +141,7 @@ fn build_client(
}
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
async fn main() -> color_eyre::Result<()> {
dotenv::dotenv().ok();
let config = Config::build()?;
@ -166,7 +167,7 @@ async fn main() -> Result<(), anyhow::Error> {
.add_recorder(recorder)
.add_recorder(collector.clone())
.build();
metrics::set_global_recorder(recorder).map_err(|e| anyhow::anyhow!("{e}"))?;
metrics::set_global_recorder(recorder).map_err(|e| color_eyre::eyre::eyre!("{e}"))?;
} else {
collector.install()?;
}
@ -185,11 +186,11 @@ async fn main() -> Result<(), anyhow::Error> {
Ok(())
}
fn client_main(config: Config, args: Args) -> JoinHandle<Result<(), anyhow::Error>> {
fn client_main(config: Config, args: Args) -> JoinHandle<color_eyre::Result<()>> {
tokio::spawn(do_client_main(config, args))
}
async fn do_client_main(config: Config, args: Args) -> Result<(), anyhow::Error> {
async fn do_client_main(config: Config, args: Args) -> color_eyre::Result<()> {
let client = build_client(
&config.user_agent(),
config.client_timeout(),
@ -280,7 +281,7 @@ async fn server_main(
media: MediaCache,
collector: MemoryCollector,
config: Config,
) -> Result<(), anyhow::Error> {
) -> color_eyre::Result<()> {
let client = build_client(
&config.user_agent(),
config.client_timeout(),
@ -320,10 +321,16 @@ async fn server_main(
let sign_spawner2 = sign_spawner.clone();
let verify_spawner2 = verify_spawner.clone();
let config2 = config.clone();
let job_store = jobs::build_storage();
let server = HttpServer::new(move || {
let job_server =
create_workers(state.clone(), actors.clone(), media.clone(), config.clone())
.expect("Failed to create job server");
let job_server = create_workers(
job_store.clone(),
state.clone(),
actors.clone(),
media.clone(),
config.clone(),
)
.expect("Failed to create job server");
let app = App::new()
.app_data(web::Data::new(db.clone()))

View file

@ -80,7 +80,7 @@ where
fn call(&self, req: ServiceRequest) -> Self::Future {
let log_on_drop = LogOnDrop {
begin: Instant::now(),
path: req.path().to_string(),
path: format!("{:?}", req.match_pattern()),
method: req.method().to_string(),
arm: false,
};

View file

@ -8,7 +8,7 @@ pub(crate) struct Spawner {
}
impl Spawner {
pub(crate) fn build(name: &'static str, threads: u16) -> anyhow::Result<Self> {
pub(crate) fn build(name: &'static str, threads: u16) -> color_eyre::Result<Self> {
let pool = CpuPool::configure()
.name(name)
.max_threads(threads)