Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c1a8f4309 | ||
|
|
29481e69df | ||
|
|
ca13282445 |
@@ -1,46 +1,94 @@
|
|||||||
name: Publish release
|
name: Publish release
|
||||||
|
|
||||||
# A `v*` tag builds the binary and attaches it to the Gitea release as
|
# A `v*` tag builds the package on each architecture's own runner
|
||||||
# `gdo`, with the tag's CHANGELOG.md section as the notes. Hosts
|
# (x86_64 on ergo's bare runner, aarch64 on klokka's) and uploads it
|
||||||
# install it with deploy/install.sh.
|
# to the [uhhm] Arch registry, like uhhm/corp and cnats. Hosts then
|
||||||
|
# `pacman -S gdo`. The tag has to agree with PKGBUILD's pkgver, and
|
||||||
|
# CHANGELOG.md has to have the section; a release with the tag's notes
|
||||||
|
# is created from the x86_64 job for the record, with no asset.
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags: ["v*"]
|
tags: ["v*"]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
package:
|
||||||
runs-on: bare
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- arch: x86_64
|
||||||
|
runs-on: bare
|
||||||
|
# The bare runner's shared toolchain and caches, with the
|
||||||
|
# writable cargo home uhhm/iris uses.
|
||||||
|
cargo_home: /var/local/cargo-target/iris-cargo-home
|
||||||
|
rustc_wrapper: /usr/bin/sccache
|
||||||
|
rustup_home: /var/local/rustup
|
||||||
|
target_dir: /var/local/cargo-target
|
||||||
|
- arch: aarch64
|
||||||
|
runs-on: aarch64
|
||||||
|
# klokka's host runner: the system cargo, defaults everywhere.
|
||||||
|
cargo_home: ""
|
||||||
|
rustc_wrapper: ""
|
||||||
|
rustup_home: ""
|
||||||
|
target_dir: ""
|
||||||
|
runs-on: ${{ matrix.runs-on }}
|
||||||
env:
|
env:
|
||||||
CARGO_HOME: /var/local/cargo-target/iris-cargo-home
|
CARGO_HOME: ${{ matrix.cargo_home }}
|
||||||
RUSTC_WRAPPER: /usr/bin/sccache
|
RUSTC_WRAPPER: ${{ matrix.rustc_wrapper }}
|
||||||
RUSTUP_HOME: /var/local/rustup
|
RUSTUP_HOME: ${{ matrix.rustup_home }}
|
||||||
|
CARGO_TARGET_DIR: ${{ matrix.target_dir }}
|
||||||
PATH: /var/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/bin
|
PATH: /var/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/bin
|
||||||
SCCACHE_DIR: /var/local/sccache
|
SCCACHE_DIR: /var/local/sccache
|
||||||
SCCACHE_SERVER_PORT: "4228"
|
SCCACHE_SERVER_PORT: "4228"
|
||||||
CARGO_TARGET_DIR: /var/local/cargo-target
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
# Plain git: the aarch64 host runner has no Node.js for
|
||||||
|
# actions/checkout (same as uhhm/corp).
|
||||||
|
- name: Checkout
|
||||||
|
run: |
|
||||||
|
git init -q .
|
||||||
|
git fetch -q --depth 1 "https://ci:${{ gitea.token }}@${GITEA_SERVER#https://}/${{ gitea.repository }}.git" "${{ gitea.sha }}"
|
||||||
|
git checkout -q FETCH_HEAD
|
||||||
|
env:
|
||||||
|
GITEA_SERVER: ${{ gitea.server_url }}
|
||||||
|
|
||||||
- name: Build
|
- name: Check tag matches pkgver
|
||||||
run: cargo build --release && cargo test --release
|
run: |
|
||||||
|
want="${GITHUB_REF_NAME#v}"
|
||||||
|
have=$(sed -n 's/^pkgver=//p' PKGBUILD)
|
||||||
|
[ "$want" = "$have" ] || { echo "tag $GITHUB_REF_NAME != pkgver $have" >&2; exit 1; }
|
||||||
|
notes=$(awk -v v="$want" '/^## /{p = ($2 == v)} p' CHANGELOG.md | tail -n +2)
|
||||||
|
[ -n "$(printf "%s" "$notes" | tr -d "[:space:]")" ] || { echo "CHANGELOG.md has no section for $GITHUB_REF_NAME" >&2; exit 1; }
|
||||||
|
|
||||||
- name: Publish release
|
# -d: cargo is the shared toolchain, not a pacman package the
|
||||||
|
# runner could verify. Builds and tests from the checkout. Empty
|
||||||
|
# env values above are unset here so cargo's defaults apply.
|
||||||
|
- name: Build package
|
||||||
|
run: |
|
||||||
|
for v in CARGO_HOME RUSTC_WRAPPER RUSTUP_HOME CARGO_TARGET_DIR; do
|
||||||
|
eval "[ -n \"\$$v\" ]" || unset "$v"
|
||||||
|
done
|
||||||
|
makepkg -f -d --noconfirm
|
||||||
|
|
||||||
|
# REGISTRY_TOKEN is a write:package token for bl, a secret on this
|
||||||
|
# repo (org repos do not inherit bl's). The registry namespace is
|
||||||
|
# always bl: pacman.conf's [uhhm] points at /api/packages/bl/arch/uhhm.
|
||||||
|
- name: Publish to the Arch package registry
|
||||||
|
run: |
|
||||||
|
for pkg in $(makepkg --packagelist); do
|
||||||
|
echo "==> $pkg"
|
||||||
|
curl --fail-with-body --user "bl:${{ secrets.REGISTRY_TOKEN }}" \
|
||||||
|
--upload-file "$pkg" \
|
||||||
|
"${{ gitea.server_url }}/api/packages/bl/arch/uhhm"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Release notes
|
||||||
|
if: matrix.arch == 'x86_64'
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
tag="${{ github.ref_name }}"
|
tag="${{ github.ref_name }}"
|
||||||
api="${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
|
api="${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
|
||||||
auth="Authorization: token ${{ secrets.GITHUB_TOKEN }}"
|
auth="Authorization: token ${{ secrets.GITHUB_TOKEN }}"
|
||||||
notes=$(awk -v v="${tag#v}" '/^## /{p = ($2 == v)} p' CHANGELOG.md | tail -n +2)
|
notes=$(awk -v v="${tag#v}" '/^## /{p = ($2 == v)} p' CHANGELOG.md | tail -n +2)
|
||||||
[ -n "$(printf "%s" "$notes" | tr -d "[:space:]")" ] || { echo "CHANGELOG.md has no section for $tag"; exit 1; }
|
|
||||||
body=$(jq -n --arg tag "$tag" --arg notes "$notes" '{tag_name: $tag, name: $tag, body: $notes}')
|
body=$(jq -n --arg tag "$tag" --arg notes "$notes" '{tag_name: $tag, name: $tag, body: $notes}')
|
||||||
id=$(curl -sf -X POST -H "$auth" -H 'Content-Type: application/json' \
|
curl -sf -X POST -H "$auth" -H 'Content-Type: application/json' -d "$body" "$api/releases" > /dev/null \
|
||||||
-d "$body" "$api/releases" | jq .id) \
|
|| echo "release $tag exists"
|
||||||
|| id=$(curl -sf -H "$auth" "$api/releases/tags/$tag" | jq .id)
|
|
||||||
for aid in $(curl -sf -H "$auth" "$api/releases/$id/assets" | jq '.[].id'); do
|
|
||||||
curl -sf -X DELETE -H "$auth" "$api/releases/$id/assets/$aid"
|
|
||||||
done
|
|
||||||
curl -sf -X POST -H "$auth" \
|
|
||||||
-F "attachment=@/var/local/cargo-target/release/gdo" \
|
|
||||||
"$api/releases/$id/assets?name=gdo" > /dev/null
|
|
||||||
echo "published $tag"
|
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
target
|
target
|
||||||
|
pkg/
|
||||||
|
*.pkg.tar.*
|
||||||
|
|||||||
+9
-1
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.1.2 (2026-09-23)
|
||||||
|
|
||||||
|
- The stream is `mail`, not shouted; matches portal 0.3.44. The unit runs the packaged binary at /usr/bin/gdo.
|
||||||
|
|
||||||
|
## 0.1.1 (2026-09-23)
|
||||||
|
|
||||||
|
- Packaged: `pacman -S gdo` from the [uhhm] registry on project.uhhm.no (x86_64 and aarch64, built by the release workflow from the tagged checkout); the unit and `/etc/gdo/env` ship in the package, and the installer script is gone.
|
||||||
|
|
||||||
## 0.1.0 (2026-09-23)
|
## 0.1.0 (2026-09-23)
|
||||||
|
|
||||||
- First release: a durable consumer `gdo` on the `WORMHOLE` stream (`portal.mail.>`), each message handed to the host's SMTP as text with an HTML alternative, acked on acceptance and retried after a minute otherwise; `gdo probe <address>` sends one message through and reports when it was delivered; an optional Typst theme (`GDO_TYPST_THEME`) renders a PDF of every mail and attaches it.
|
- First release: a durable consumer `gdo` on the `mail` stream (`portal.mail.>`), each message handed to the host's SMTP as text with an HTML alternative, acked on acceptance and retried after a minute otherwise; `gdo probe <address>` sends one message through and reports when it was delivered; an optional Typst theme (`GDO_TYPST_THEME`) renders a PDF of every mail and attaches it.
|
||||||
|
|||||||
Generated
+1
-1
@@ -411,7 +411,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdo"
|
name = "gdo"
|
||||||
version = "0.1.0"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-nats",
|
"async-nats",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "gdo"
|
name = "gdo"
|
||||||
version = "0.1.0"
|
version = "0.1.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Sends the code that opens the iris: delivers portal's outgoing mail from JetStream to the host's SMTP"
|
description = "Sends the code that opens the iris: delivers portal's outgoing mail from JetStream to the host's SMTP"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Bendik Aagaard Lynghaug
|
||||||
|
|
||||||
|
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.
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# Maintainer: Bendik Aagaard Lynghaug <bendik.lynghaug@gmail.com>
|
||||||
|
# Built from the tagged checkout by .gitea/workflows/release.yml, once
|
||||||
|
# per architecture, and uploaded to the [uhhm] registry on
|
||||||
|
# project.uhhm.no (namespace bl). pkgver is the version; the tag has
|
||||||
|
# to agree with it.
|
||||||
|
pkgname=gdo
|
||||||
|
pkgver=0.1.2
|
||||||
|
pkgrel=1
|
||||||
|
pkgdesc="Sends the code that opens the iris: delivers portal's outgoing mail from JetStream to the host's SMTP"
|
||||||
|
arch=('x86_64' 'aarch64')
|
||||||
|
url="https://project.uhhm.no/uhhm/gdo"
|
||||||
|
license=('MIT')
|
||||||
|
depends=('glibc' 'gcc-libs')
|
||||||
|
makedepends=('cargo')
|
||||||
|
optdepends=('postfix: the SMTP it hands mail to'
|
||||||
|
'nats-server: the JetStream it reads from'
|
||||||
|
'typst: PDF themes (GDO_TYPST_THEME)')
|
||||||
|
backup=('etc/gdo/env')
|
||||||
|
# !lto: makepkg's -flto would turn ring's C objects into GCC bitcode the
|
||||||
|
# Rust linker cannot see (undefined ring_core_* symbols).
|
||||||
|
options=('!debug' '!lto')
|
||||||
|
|
||||||
|
# Sources are the checkout itself: makepkg resolves local sources by
|
||||||
|
# basename next to the PKGBUILD, so the tagged tree CI builds from is
|
||||||
|
# the source of truth, as in uhhm/corp.
|
||||||
|
|
||||||
|
build() {
|
||||||
|
cd "$startdir"
|
||||||
|
cargo build --release --locked
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
cd "$startdir"
|
||||||
|
cargo test --release --locked
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "$startdir"
|
||||||
|
install -Dm755 "${CARGO_TARGET_DIR:-target}/release/gdo" "$pkgdir/usr/bin/gdo"
|
||||||
|
install -Dm644 deploy/gdo.service "$pkgdir/usr/lib/systemd/system/gdo.service"
|
||||||
|
install -Dm600 deploy/env "$pkgdir/etc/gdo/env"
|
||||||
|
install -Dm644 README.md "$pkgdir/usr/share/doc/$pkgname/README.md"
|
||||||
|
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ site's content says to send.
|
|||||||
Portal decides *when* a person hears something and renders the mail:
|
Portal decides *when* a person hears something and renders the mail:
|
||||||
`mail:` on a state in `aggregates.yaml` sends when a record enters
|
`mail:` on a state in `aggregates.yaml` sends when a record enters
|
||||||
that state, and an invite mails its one-time link built in. It
|
that state, and an invite mails its one-time link built in. It
|
||||||
publishes each rendered mail on `portal.mail.send` in the `WORMHOLE`
|
publishes each rendered mail on `portal.mail.send` in the `mail`
|
||||||
JetStream stream. gdo holds a durable consumer there and hands each
|
JetStream stream. gdo holds a durable consumer there and hands each
|
||||||
message to the host's SMTP. Portal never talks SMTP; gdo never reads
|
message to the host's SMTP. Portal never talks SMTP; gdo never reads
|
||||||
content; a message survives either of them being down, because the
|
content; a message survives either of them being down, because the
|
||||||
@@ -31,16 +31,18 @@ gdo --version
|
|||||||
| `GDO_CONSUMER` | `gdo` | the durable consumer's name |
|
| `GDO_CONSUMER` | `gdo` | the durable consumer's name |
|
||||||
| `GDO_TYPST_THEME` | unset | a `.typ` file; set, every mail carries a PDF rendered from it |
|
| `GDO_TYPST_THEME` | unset | a `.typ` file; set, every mail carries a PDF rendered from it |
|
||||||
|
|
||||||
Install on a host from a release, as root:
|
Install on a host from the [uhhm] Arch registry on project.uhhm.no
|
||||||
|
(the repo and its key: see uhhm/corp's README), as root:
|
||||||
|
|
||||||
```
|
```
|
||||||
curl -sfLO https://project.uhhm.no/uhhm/gdo/raw/branch/main/deploy/install.sh
|
pacman -Sy gdo
|
||||||
sudo sh install.sh v0.1.0 'nats://infra:<token>@127.0.0.1:4222'
|
<edit /etc/gdo/env: NATS_URL with the host's credentials>
|
||||||
|
systemctl enable --now gdo
|
||||||
```
|
```
|
||||||
|
|
||||||
That puts the binary in `/usr/local/bin`, the env in `/etc/gdo.env`
|
The package puts the binary in `/usr/bin`, the env template in
|
||||||
(mode 0600, the one file with a secret), and the unit
|
`/etc/gdo/env` (mode 0600, the one file with a secret), and the unit
|
||||||
`deploy/gdo.service` enabled and running. Then `gdo probe <you>`.
|
`gdo.service`. Then `gdo probe <you>`, with the env loaded.
|
||||||
|
|
||||||
## The message
|
## The message
|
||||||
|
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
# gdo - one per host. Read by gdo.service; mode 0600, the one file
|
||||||
|
# with a secret in it. See /usr/share/doc/gdo/README.md.
|
||||||
|
NATS_URL=nats://127.0.0.1:4222
|
||||||
|
SMTP_HOST=127.0.0.1
|
||||||
|
SMTP_PORT=25
|
||||||
|
# What gdo says in EHLO; a strict server refuses a bare hostname.
|
||||||
|
# Unset, the host's full name is used.
|
||||||
|
#SMTP_HELO=host.example.no
|
||||||
|
# A .typ file: set, every mail carries a PDF rendered from it.
|
||||||
|
#GDO_TYPST_THEME=/etc/gdo/theme.typ
|
||||||
+4
-4
@@ -1,14 +1,14 @@
|
|||||||
# One per host, not per site: every portal instance on the host
|
# One per host, not per site: every portal instance on the host
|
||||||
# publishes to the same WORMHOLE stream, and each message carries its
|
# publishes to the same mail stream, and each message carries its
|
||||||
# own sender. Install with deploy/install.sh.
|
# own sender. Installed by the gdo package (pacman -S gdo).
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=gdo - delivers portal's outgoing mail to the host's SMTP
|
Description=gdo - delivers portal's outgoing mail to the host's SMTP
|
||||||
After=network-online.target nats-server.service postfix.service
|
After=network-online.target nats-server.service postfix.service
|
||||||
Wants=network-online.target
|
Wants=network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=/usr/local/bin/gdo
|
ExecStart=/usr/bin/gdo
|
||||||
EnvironmentFile=-/etc/gdo.env
|
EnvironmentFile=-/etc/gdo/env
|
||||||
DynamicUser=yes
|
DynamicUser=yes
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# Install or upgrade gdo on this host from a Gitea release. Run as root:
|
|
||||||
# sudo sh install.sh v0.1.0 [nats://user:pass@127.0.0.1:4222]
|
|
||||||
# The NATS URL is only needed the first time; it lands in /etc/gdo.env,
|
|
||||||
# which is the one file with a secret in it (mode 0600).
|
|
||||||
set -eu
|
|
||||||
tag=${1:?usage: install.sh vX.Y.Z [NATS_URL]}
|
|
||||||
base=https://project.uhhm.no/uhhm/gdo
|
|
||||||
tmp=$(mktemp)
|
|
||||||
curl -sfL "$base/releases/download/$tag/gdo" -o "$tmp"
|
|
||||||
install -m 0755 "$tmp" /usr/local/bin/gdo
|
|
||||||
rm -f "$tmp"
|
|
||||||
if [ ! -f /etc/gdo.env ]; then
|
|
||||||
nats=${2:-nats://127.0.0.1:4222}
|
|
||||||
umask 077
|
|
||||||
printf 'NATS_URL=%s\nSMTP_HOST=127.0.0.1\nSMTP_PORT=25\nSMTP_HELO=%s\n# GDO_TYPST_THEME=/etc/gdo/theme.typ\n' "$nats" "$(hostname -f 2>/dev/null || cat /etc/hostname)" > /etc/gdo.env
|
|
||||||
fi
|
|
||||||
curl -sfL "$base/raw/tag/$tag/deploy/gdo.service" -o /etc/systemd/system/gdo.service
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable --now gdo
|
|
||||||
systemctl restart gdo
|
|
||||||
sleep 2
|
|
||||||
systemctl is-active gdo && /usr/local/bin/gdo --version
|
|
||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
//! gdo - the transmitter that sends the code through the gate so the
|
//! gdo - the transmitter that sends the code through the gate so the
|
||||||
//! iris opens. Portal (uhhm/portal) decides when a person hears
|
//! iris opens. Portal (uhhm/portal) decides when a person hears
|
||||||
//! something and renders the mail; gdo holds a durable consumer on
|
//! something and renders the mail; gdo holds a durable consumer on
|
||||||
//! the `WORMHOLE` stream and hands each message to the host's SMTP.
|
//! the `mail` stream and hands each message to the host's SMTP.
|
||||||
//! No site knowledge, no state of its own: if it dies, the stream
|
//! No site knowledge, no state of its own: if it dies, the stream
|
||||||
//! keeps the mail until it is back.
|
//! keeps the mail until it is back.
|
||||||
//!
|
//!
|
||||||
@@ -22,7 +22,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
/// Portal's side of this contract is `portal::mail`. Same names, same
|
/// Portal's side of this contract is `portal::mail`. Same names, same
|
||||||
/// stream config, so whichever boots first creates it.
|
/// stream config, so whichever boots first creates it.
|
||||||
const STREAM: &str = "WORMHOLE";
|
const STREAM: &str = "mail";
|
||||||
const SUBJECTS: &str = "portal.mail.>";
|
const SUBJECTS: &str = "portal.mail.>";
|
||||||
const SUBJECT: &str = "portal.mail.send";
|
const SUBJECT: &str = "portal.mail.send";
|
||||||
const CONTRACT: u8 = 1;
|
const CONTRACT: u8 = 1;
|
||||||
@@ -255,7 +255,7 @@ async fn probe(cfg: Config, to: &str, from: &str) -> anyhow::Result<()> {
|
|||||||
let mut headers = async_nats::HeaderMap::new();
|
let mut headers = async_nats::HeaderMap::new();
|
||||||
headers.insert("Nats-Msg-Id", id.as_str());
|
headers.insert("Nats-Msg-Id", id.as_str());
|
||||||
js.publish_with_headers(SUBJECT, headers, serde_json::to_vec(&mail)?.into()).await?.await?;
|
js.publish_with_headers(SUBJECT, headers, serde_json::to_vec(&mail)?.into()).await?.await?;
|
||||||
println!("sent {id} into {STREAM}");
|
println!("sent {id} into stream {STREAM}");
|
||||||
let deadline = tokio::time::Instant::now() + Duration::from_secs(60);
|
let deadline = tokio::time::Instant::now() + Duration::from_secs(60);
|
||||||
loop {
|
loop {
|
||||||
let Ok(mut consumer) = stream.get_consumer::<async_nats::jetstream::consumer::pull::Config>(&cfg.consumer).await else {
|
let Ok(mut consumer) = stream.get_consumer::<async_nats::jetstream::consumer::pull::Config>(&cfg.consumer).await else {
|
||||||
|
|||||||
Reference in New Issue
Block a user