mirror of
https://github.com/element-hq/synapse.git
synced 2026-11-05 15:27:36 +00:00
Phase 0 of the event persistence plan, apart from the write transaction helper: - `experimental_features.rust_event_persistence`, one ordered level (off, shadow, prepare, transaction, full). Nothing uses the levels yet beyond building the persister. - `RustHandlers.persister`: built on the events writer when the level is not off and the main database uses the native driver. It holds the pool, the shared caches and the events, backfill and cache stream trackers. - `PersistEffects`, the Python cache updates a Rust transaction will ask for in place of `txn.call_after`, applied in one call by `DataStore._apply_rust_persist_effects`. A test persists batches through Python and checks that applying the matching effects updates the same caches. The chunk's stream IDs come back unfinished and are finished last, as Python's `get_next_mult` does after the transaction's callbacks, so the current token never passes an event the stream change caches don't know about. - `PersistContext`, read from an `EventContext` once per event. - `Event::to_persistence_value` and `EventInternalMetadata::to_persistence_value`: the `event_json` columns built without the GIL. - Rust-side persistence counters, added to the Python metrics by a pre-collect hook. A homeserver can now register more than one such hook. The persisted position is reported only when it moved, so it can't pull back the gauge the Python path sets. - `SYNAPSE_TEST_RUST_PERSIST` for trial and `RUST_PERSIST` for Complement. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UHKYPSc37kWqGACn9aKxKL
156 lines
5.6 KiB
Bash
Executable File
156 lines
5.6 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Default ENTRYPOINT for the docker image used for testing synapse with workers under complement
|
|
|
|
set -e
|
|
|
|
echo "Complement Synapse launcher"
|
|
echo " Args: $*"
|
|
echo " Env: SYNAPSE_COMPLEMENT_DATABASE=$SYNAPSE_COMPLEMENT_DATABASE SYNAPSE_COMPLEMENT_USE_WORKERS=$SYNAPSE_COMPLEMENT_USE_WORKERS SYNAPSE_COMPLEMENT_USE_ASYNCIO_REACTOR=$SYNAPSE_COMPLEMENT_USE_ASYNCIO_REACTOR SYNAPSE_USE_RUST_DRIVER=$SYNAPSE_USE_RUST_DRIVER SYNAPSE_RUST_STATE_RES=$SYNAPSE_RUST_STATE_RES SYNAPSE_RUST_SYNC=$SYNAPSE_RUST_SYNC SYNAPSE_RUST_PERSIST=$SYNAPSE_RUST_PERSIST"
|
|
|
|
function log {
|
|
d=$(printf '%(%Y-%m-%d %H:%M:%S)T,%.3s\n' ${EPOCHREALTIME/./ })
|
|
echo "$d $*"
|
|
}
|
|
|
|
# Set the server name of the homeserver
|
|
export SYNAPSE_SERVER_NAME=${SERVER_NAME}
|
|
|
|
# No need to report stats here
|
|
export SYNAPSE_REPORT_STATS=no
|
|
|
|
|
|
case "$SYNAPSE_COMPLEMENT_DATABASE" in
|
|
postgres)
|
|
# Set postgres authentication details which will be placed in the homeserver config file
|
|
export POSTGRES_PASSWORD=somesecret
|
|
export POSTGRES_USER=postgres
|
|
export POSTGRES_HOST=localhost
|
|
|
|
# configure supervisord to start postgres
|
|
export START_POSTGRES=true
|
|
;;
|
|
|
|
sqlite|"")
|
|
# Set START_POSTGRES to false unless it has already been set
|
|
# (i.e. by another container image inheriting our own).
|
|
export START_POSTGRES=${START_POSTGRES:-false}
|
|
;;
|
|
|
|
*)
|
|
echo "Unknown Synapse database: SYNAPSE_COMPLEMENT_DATABASE=$SYNAPSE_COMPLEMENT_DATABASE" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
|
|
if [[ -n "$SYNAPSE_COMPLEMENT_USE_WORKERS" ]]; then
|
|
# Specify the workers to test with
|
|
# Allow overriding by explicitly setting SYNAPSE_WORKER_TYPES outside, while still
|
|
# utilizing WORKERS=1 for backwards compatibility.
|
|
# -n True if the length of string is non-zero.
|
|
# -z True if the length of string is zero.
|
|
if [[ -z "$SYNAPSE_WORKER_TYPES" ]]; then
|
|
export SYNAPSE_WORKER_TYPES="\
|
|
event_persister:2, \
|
|
background_worker, \
|
|
event_creator, \
|
|
user_dir, \
|
|
media_repository, \
|
|
federation_inbound, \
|
|
federation_reader, \
|
|
federation_sender, \
|
|
synchrotron, \
|
|
client_reader, \
|
|
appservice, \
|
|
pusher, \
|
|
device_lists:2, \
|
|
stream_writers=account_data+presence+receipts+to_device+typing"
|
|
|
|
fi
|
|
log "Workers requested: $SYNAPSE_WORKER_TYPES"
|
|
# adjust connection pool limits on worker mode as otherwise running lots of worker synapses
|
|
# can make docker unhappy (in GHA)
|
|
export POSTGRES_CP_MIN=1
|
|
export POSTGRES_CP_MAX=3
|
|
echo "using reduced connection pool limits for worker mode"
|
|
# Improve startup times by using a launcher based on fork()
|
|
export SYNAPSE_USE_EXPERIMENTAL_FORKING_LAUNCHER=1
|
|
else
|
|
# Empty string here means 'main process only'
|
|
export SYNAPSE_WORKER_TYPES=""
|
|
fi
|
|
|
|
|
|
if [[ -n "$SYNAPSE_COMPLEMENT_USE_ASYNCIO_REACTOR" ]]; then
|
|
if [[ -n "$SYNAPSE_USE_EXPERIMENTAL_FORKING_LAUNCHER" ]]; then
|
|
export SYNAPSE_COMPLEMENT_FORKING_LAUNCHER_ASYNC_IO_REACTOR="1"
|
|
else
|
|
export SYNAPSE_ASYNC_IO_REACTOR="1"
|
|
fi
|
|
else
|
|
export SYNAPSE_ASYNC_IO_REACTOR="0"
|
|
fi
|
|
|
|
|
|
# Add Complement's appservice registration directory, if there is one
|
|
# (It can be absent when there are no application services in this test!)
|
|
if [ -d /complement/appservice ]; then
|
|
export SYNAPSE_AS_REGISTRATION_DIR=/complement/appservice
|
|
fi
|
|
|
|
# Generate a TLS key, then generate a certificate by having Complement's CA sign it
|
|
# Note that both the key and certificate are in PEM format (not DER).
|
|
|
|
# First generate a configuration file to set up a Subject Alternative Name.
|
|
echo "\
|
|
.include /etc/ssl/openssl.cnf
|
|
|
|
[SAN]
|
|
subjectAltName=DNS:${SERVER_NAME}" > /conf/server.tls.conf
|
|
|
|
# Generate an RSA key
|
|
openssl genrsa -out /conf/server.tls.key 2048
|
|
|
|
# Generate a certificate signing request
|
|
openssl req -new -config /conf/server.tls.conf -key /conf/server.tls.key -out /conf/server.tls.csr \
|
|
-subj "/CN=${SERVER_NAME}" -reqexts SAN
|
|
|
|
# Make the Complement Certificate Authority sign and generate a certificate.
|
|
openssl x509 -req -in /conf/server.tls.csr \
|
|
-CA /complement/ca/ca.crt -CAkey /complement/ca/ca.key -set_serial 1 \
|
|
-out /conf/server.tls.crt -extfile /conf/server.tls.conf -extensions SAN
|
|
|
|
# Assert that we have a Subject Alternative Name in the certificate.
|
|
# (the test will exit with 1 here if there isn't a SAN in the certificate.)
|
|
[[ $(openssl x509 -in /conf/server.tls.crt -noout -text) == *DNS:* ]]
|
|
|
|
export SYNAPSE_TLS_CERT=/conf/server.tls.crt
|
|
export SYNAPSE_TLS_KEY=/conf/server.tls.key
|
|
|
|
# Resolve state in Rust (`experimental_features.rust_state_res`). This goes into
|
|
# the shared config's `experimental_features`, as a config snippet with its own
|
|
# `experimental_features` would replace the shared one.
|
|
if [[ -n "$SYNAPSE_RUST_STATE_RES" ]]; then
|
|
sed -i "s/^experimental_features:$/experimental_features:\n rust_state_res: \"$SYNAPSE_RUST_STATE_RES\"/" /conf/shared.yaml.j2
|
|
fi
|
|
|
|
# Compute sync rooms in Rust (`experimental_features.rust_sync`), allowing the
|
|
# two event caches a test homeserver can afford.
|
|
if [[ -n "$SYNAPSE_RUST_SYNC" ]]; then
|
|
sed -i "s/^experimental_features:$/experimental_features:\n rust_sync: \"$SYNAPSE_RUST_SYNC\"/" /conf/shared.yaml.j2
|
|
fi
|
|
|
|
# Persist events in Rust (`experimental_features.rust_event_persistence`).
|
|
if [[ -n "$SYNAPSE_RUST_PERSIST" ]]; then
|
|
sed -i "s/^experimental_features:$/experimental_features:\n rust_event_persistence: \"$SYNAPSE_RUST_PERSIST\"/" /conf/shared.yaml.j2
|
|
fi
|
|
|
|
# Add a directory for tests to add config overrides if they want
|
|
mkdir --parents /conf/homeserver.d
|
|
export _SYNAPSE_COMPLEMENT_EXTRA_CONFIG_DIR=/conf/homeserver.d
|
|
|
|
# Run the script that writes the necessary config files and starts supervisord, which in turn
|
|
# starts everything else
|
|
exec /configure_workers_and_start.py "$@"
|