Allow multiple FoundationDB instances in the same process
This commit is contained in:
@@ -18,6 +18,7 @@ If you are upgrading from v0.16.x, replace the binary (or run `docker pull`). If
|
||||
- Spam filter: Use original instead of rewritten `RCPT` on checks.
|
||||
- JMAP references in nested objects not resolved.
|
||||
- Import tool fails to restore registry entries.
|
||||
- FDB: Allow multiple FoundationDB instances in the same process.
|
||||
|
||||
## [0.16.3] - 2026-04-30
|
||||
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM debian:trixie-slim AS chef
|
||||
ARG TARGETARCH
|
||||
ARG FDB_VERSION_RANGE="7.4"
|
||||
RUN apt-get update && \
|
||||
export DEBIAN_FRONTEND=noninteractive && \
|
||||
apt-get install -yq \
|
||||
apt-get install -yq --no-install-recommends \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
cmake \
|
||||
clang \
|
||||
curl \
|
||||
protobuf-compiler \
|
||||
adduser
|
||||
jq \
|
||||
protobuf-compiler
|
||||
ENV RUSTUP_HOME=/opt/rust/rustup \
|
||||
PATH=/home/root/.cargo/bin:/opt/rust/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
RUN curl https://sh.rustup.rs -sSf | \
|
||||
@@ -15,8 +20,19 @@ RUN curl https://sh.rustup.rs -sSf | \
|
||||
sh -s -- -y --default-toolchain stable --profile minimal --no-modify-path && \
|
||||
env CARGO_HOME=/opt/rust/cargo \
|
||||
rustup component add rustfmt
|
||||
RUN curl -LO https://github.com/apple/foundationdb/releases/download/7.3.69/foundationdb-clients_7.3.69-1_amd64.deb && \
|
||||
dpkg -i foundationdb-clients_7.3.69-1_amd64.deb
|
||||
RUN \
|
||||
ARCH="${TARGETARCH:-$(dpkg --print-architecture)}" && \
|
||||
case "$ARCH" in \
|
||||
amd64) FDB_ARCH=amd64 ;; \
|
||||
arm64) FDB_ARCH=aarch64 ;; \
|
||||
*) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \
|
||||
esac && \
|
||||
curl --retry 5 -fLso fdb-client.deb "$(curl --retry 5 -fLs 'https://api.github.com/repos/apple/foundationdb/releases?per_page=100' | jq --arg FDB_ARCH "$FDB_ARCH" --arg RANGE "${FDB_VERSION_RANGE}" -r '[.[] | select(.tag_name | startswith($RANGE + "."))] | sort_by(.tag_name | split(".") | map(tonumber)) | reverse | .[0].assets[] | select(.name | test("foundationdb-clients.*" + $FDB_ARCH + ".deb$")) | .browser_download_url')" && \
|
||||
mkdir -p /fdb && \
|
||||
dpkg -x fdb-client.deb /fdb && \
|
||||
mv /fdb/usr/include/foundationdb /usr/include && \
|
||||
mv /fdb/usr/lib/libfdb_c.so /usr/lib && \
|
||||
rm -rf fdb-client.deb /fdb
|
||||
RUN env CARGO_HOME=/opt/rust/cargo cargo install cargo-chef && \
|
||||
rm -rf /opt/rust/cargo/registry/
|
||||
WORKDIR /app
|
||||
@@ -42,12 +58,10 @@ RUN cargo build -p stalwart --no-default-features --features "foundationdb s3 re
|
||||
FROM debian:trixie-slim AS runtime
|
||||
|
||||
COPY --from=builder --chmod=0755 /app/target/release/stalwart /usr/local/bin/stalwart
|
||||
COPY --from=builder /usr/lib/libfdb_c.so /usr/lib/libfdb_c.so
|
||||
RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
apt-get update && \
|
||||
apt-get install -yq --no-install-recommends ca-certificates curl libcap2-bin && \
|
||||
curl -LO https://github.com/apple/foundationdb/releases/download/7.3.69/foundationdb-clients_7.3.69-1_amd64.deb && \
|
||||
dpkg -i foundationdb-clients_7.3.69-1_amd64.deb && \
|
||||
rm -f foundationdb-clients_7.3.69-1_amd64.deb && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
groupadd -r -g 2000 stalwart && \
|
||||
useradd -r -u 2000 -g 2000 -s /usr/sbin/nologin -M stalwart && \
|
||||
|
||||
@@ -29,7 +29,7 @@ use crate::registry::{
|
||||
};
|
||||
use common::{
|
||||
Server, auth::AccessToken, cache::invalidate::CacheInvalidationBuilder,
|
||||
expr::if_block::BootstrapExprExt,
|
||||
expr::if_block::BootstrapExprExt, ipc::CacheInvalidation,
|
||||
};
|
||||
use http_proto::HttpSessionData;
|
||||
use jmap_proto::{
|
||||
@@ -649,8 +649,18 @@ impl RegistrySet for Server {
|
||||
.await?
|
||||
{
|
||||
RegistryWriteResult::Success(_) => {
|
||||
// Schedule account deletion
|
||||
if let ObjectInner::Account(account) = &object.inner {
|
||||
for sharee_id in self
|
||||
.store()
|
||||
.acl_revoke_all(id.document_id())
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
{
|
||||
cache_invalidator.invalidate(
|
||||
CacheInvalidation::AccessToken(sharee_id),
|
||||
);
|
||||
}
|
||||
|
||||
schedule_account_destruction(set.server, id, account).await?;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,19 +6,28 @@
|
||||
|
||||
use super::FdbStore;
|
||||
use crate::Store;
|
||||
use foundationdb::{Database, api, options::DatabaseOption};
|
||||
use foundationdb::{Database, api, api::NetworkAutoStop, options::DatabaseOption};
|
||||
use parking_lot::Mutex;
|
||||
use registry::schema::structs;
|
||||
use std::sync::Arc;
|
||||
|
||||
static FDB_NETWORK: Mutex<Option<NetworkAutoStop>> = Mutex::new(None);
|
||||
|
||||
impl FdbStore {
|
||||
pub async fn open(config: structs::FoundationDbStore) -> Result<Store, String> {
|
||||
let guard = unsafe {
|
||||
api::FdbApiBuilder::default()
|
||||
.build()
|
||||
.map_err(|err| format!("Failed to boot FoundationDB: {err:?}"))?
|
||||
.boot()
|
||||
.map_err(|err| format!("Failed to boot FoundationDB: {err:?}"))?
|
||||
};
|
||||
{
|
||||
let mut guard = FDB_NETWORK.lock();
|
||||
if guard.is_none() {
|
||||
let network = unsafe {
|
||||
api::FdbApiBuilder::default()
|
||||
.build()
|
||||
.map_err(|err| format!("Failed to boot FoundationDB: {err:?}"))?
|
||||
.boot()
|
||||
.map_err(|err| format!("Failed to boot FoundationDB: {err:?}"))?
|
||||
};
|
||||
*guard = Some(network);
|
||||
}
|
||||
}
|
||||
|
||||
let db = Database::new(config.cluster_file.as_deref())
|
||||
.map_err(|err| format!("Failed to create FoundationDB database: {err:?}"))?;
|
||||
@@ -49,7 +58,6 @@ impl FdbStore {
|
||||
}
|
||||
|
||||
Ok(Store::FoundationDb(Arc::new(Self {
|
||||
guard,
|
||||
db,
|
||||
version: Default::default(),
|
||||
})))
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use foundationdb::{Database, FdbError, api::NetworkAutoStop};
|
||||
use foundationdb::{Database, FdbError};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub mod blob;
|
||||
@@ -15,10 +15,8 @@ pub mod write;
|
||||
const MAX_VALUE_SIZE: usize = 100000;
|
||||
pub const TRANSACTION_EXPIRY: Duration = Duration::from_secs(1);
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct FdbStore {
|
||||
db: Database,
|
||||
guard: NetworkAutoStop,
|
||||
version: parking_lot::Mutex<ReadVersion>,
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ edition = "2024"
|
||||
[features]
|
||||
#default = ["sqlite", "postgres", "mysql", "rocks", "s3", "redis", "nats", "azure", "foundationdb"]
|
||||
#default = ["sqlite", "postgres", "mysql", "rocks", "s3", "redis", "foundationdb"]
|
||||
default = ["rocks", "s3"]
|
||||
default = ["rocks"]
|
||||
sqlite = ["store/sqlite", "directory/sqlite"]
|
||||
foundationdb = ["store/foundation", "common/foundation"]
|
||||
postgres = ["store/postgres", "directory/postgres"]
|
||||
|
||||
@@ -60,11 +60,18 @@ services:
|
||||
tmpfs:
|
||||
- /var/fdb/data
|
||||
- /var/fdb/logs
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "fdbcli --exec 'status' --timeout 3 >/dev/null 2>&1" ]
|
||||
interval: 2s
|
||||
timeout: 5s
|
||||
retries: 30
|
||||
start_period: 5s
|
||||
|
||||
fdb-init:
|
||||
image: foundationdb/foundationdb:7.4.6
|
||||
depends_on:
|
||||
- foundationdb
|
||||
foundationdb:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- fdb-config:/var/fdb
|
||||
- ./scripts/init-fdb.sh:/init-fdb.sh:ro
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
set -eu
|
||||
|
||||
fdbcli --exec "configure new single memory"
|
||||
echo "FoundationDB configured."
|
||||
exit 0
|
||||
for i in $(seq 1 30); do
|
||||
if fdbcli --exec 'status minimal' --timeout 5 2>&1 | grep -q "The database is available"; then
|
||||
echo "FoundationDB already configured."
|
||||
exit 0
|
||||
fi
|
||||
if fdbcli --exec 'configure new single memory' --timeout 5 2>&1 | grep -q "Database created"; then
|
||||
echo "FoundationDB configured."
|
||||
exit 0
|
||||
fi
|
||||
echo "Waiting for FoundationDB to be ready (attempt $i)..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "ERROR: Failed to configure FoundationDB after retries" >&2
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user