Compare commits

..

6 commits

Author SHA1 Message Date
nexy7574
cf7da3a9b4
feat(PR977): Log more things in the join process 2025-09-07 20:50:54 +01:00
nexy7574
f46cb6b15c
perf(pr977): Remove redundant ACL check in send_join 2025-09-07 20:50:44 +01:00
nexy7574
048157197e
fix(PR977): Adjust some log levels 2025-09-07 20:50:37 +01:00
nexy7574
7d404486fe
fix(PR977): Omitting redundant entries from the auth_chain caused problems 2025-09-07 20:50:31 +01:00
nexy7574
4aeb9b721f
feat(PR977): Support omitting members in the send_join response 2025-09-07 20:50:19 +01:00
Tom Foster
1e9701f379 ci(release-image): Skip setup steps when using persistent BuildKit
When BUILDKIT_ENDPOINT is set, builds run on a persistent BuildKit instance,
making runner setup steps unnecessary. Skip Rust toolchain installation,
QEMU setup, caching steps, and timelord to eliminate ~7 operations per job.

Also adds output to git SHA and timestamp steps for visibility.

Cuts at least a minute off average build time through fewer installs,
cache restores, and cache saves.
2025-09-07 18:59:05 +01:00
2 changed files with 40 additions and 43 deletions

View file

@ -101,6 +101,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Install rust - name: Install rust
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
id: rust-toolchain id: rust-toolchain
uses: ./.forgejo/actions/rust-toolchain uses: ./.forgejo/actions/rust-toolchain
@ -111,6 +112,7 @@ jobs:
driver: ${{ env.BUILDKIT_ENDPOINT != '' && 'remote' || 'docker-container' }} driver: ${{ env.BUILDKIT_ENDPOINT != '' && 'remote' || 'docker-container' }}
endpoint: ${{ env.BUILDKIT_ENDPOINT || '' }} endpoint: ${{ env.BUILDKIT_ENDPOINT || '' }}
- name: Set up QEMU - name: Set up QEMU
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v3
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Login to builtin registry - name: Login to builtin registry
@ -140,15 +142,21 @@ jobs:
run: | run: |
calculatedSha=$(git rev-parse --short ${{ github.sha }}) calculatedSha=$(git rev-parse --short ${{ github.sha }})
echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV
echo "Short SHA: $calculatedSha"
- name: Get Git commit timestamps - name: Get Git commit timestamps
run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV run: |
timestamp=$(git log -1 --pretty=%ct)
echo "TIMESTAMP=$timestamp" >> $GITHUB_ENV
echo "Commit timestamp: $timestamp"
- uses: ./.forgejo/actions/timelord - uses: ./.forgejo/actions/timelord
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
with: with:
key: timelord-v0 key: timelord-v0
path: . path: .
- name: Cache Rust registry - name: Cache Rust registry
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
@ -158,6 +166,7 @@ jobs:
.cargo/registry/src .cargo/registry/src
key: rust-registry-image-${{hashFiles('**/Cargo.lock') }} key: rust-registry-image-${{hashFiles('**/Cargo.lock') }}
- name: Cache cargo target - name: Cache cargo target
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
id: cache-cargo-target id: cache-cargo-target
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
@ -165,6 +174,7 @@ jobs:
cargo-target-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }} cargo-target-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }}
key: cargo-target-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }}-${{hashFiles('**/Cargo.lock') }}-${{steps.rust-toolchain.outputs.rustc_version}} key: cargo-target-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }}-${{hashFiles('**/Cargo.lock') }}-${{steps.rust-toolchain.outputs.rustc_version}}
- name: Cache apt cache - name: Cache apt cache
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
id: cache-apt id: cache-apt
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
@ -172,6 +182,7 @@ jobs:
var-cache-apt-${{ matrix.slug }} var-cache-apt-${{ matrix.slug }}
key: var-cache-apt-${{ matrix.slug }} key: var-cache-apt-${{ matrix.slug }}
- name: Cache apt lib - name: Cache apt lib
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
id: cache-apt-lib id: cache-apt-lib
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
@ -179,6 +190,7 @@ jobs:
var-lib-apt-${{ matrix.slug }} var-lib-apt-${{ matrix.slug }}
key: var-lib-apt-${{ matrix.slug }} key: var-lib-apt-${{ matrix.slug }}
- name: inject cache into docker - name: inject cache into docker
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
uses: https://github.com/reproducible-containers/buildkit-cache-dance@v3.3.0 uses: https://github.com/reproducible-containers/buildkit-cache-dance@v3.3.0
with: with:
cache-map: | cache-map: |

View file

@ -56,8 +56,10 @@ async fn create_join_event(
// We do not add the event_id field to the pdu here because of signature and // We do not add the event_id field to the pdu here because of signature and
// hashes checks // hashes checks
trace!("Getting room version");
let room_version_id = services.rooms.state.get_room_version(room_id).await?; let room_version_id = services.rooms.state.get_room_version(room_id).await?;
trace!("Generating event ID and converting to canonical json");
let Ok((event_id, mut value)) = gen_event_id_canonical_json(pdu, &room_version_id) else { let Ok((event_id, mut value)) = gen_event_id_canonical_json(pdu, &room_version_id) else {
// Event could not be converted to canonical json // Event could not be converted to canonical json
return Err!(Request(BadJson("Could not convert event to canonical json."))); return Err!(Request(BadJson("Could not convert event to canonical json.")));
@ -106,7 +108,6 @@ async fn create_join_event(
))); )));
} }
// ACL check sender user server name
let sender: OwnedUserId = serde_json::from_value( let sender: OwnedUserId = serde_json::from_value(
value value
.get("sender") .get("sender")
@ -116,12 +117,6 @@ async fn create_join_event(
) )
.map_err(|e| err!(Request(BadJson(warn!("sender property is not a valid user ID: {e}")))))?; .map_err(|e| err!(Request(BadJson(warn!("sender property is not a valid user ID: {e}")))))?;
services
.rooms
.event_handler
.acl_check(sender.server_name(), room_id)
.await?;
// check if origin server is trying to send for another server // check if origin server is trying to send for another server
if sender.server_name() != origin { if sender.server_name() != origin {
return Err!(Request(Forbidden("Not allowed to join on behalf of another server."))); return Err!(Request(Forbidden("Not allowed to join on behalf of another server.")));
@ -183,11 +178,6 @@ async fn create_join_event(
} }
} }
services
.server_keys
.hash_and_sign_event(&mut value, &room_version_id)
.map_err(|e| err!(Request(InvalidParam(warn!("Failed to sign send_join event: {e}")))))?;
let origin: OwnedServerName = serde_json::from_value( let origin: OwnedServerName = serde_json::from_value(
value value
.get("origin") .get("origin")
@ -197,6 +187,12 @@ async fn create_join_event(
) )
.map_err(|e| err!(Request(BadJson("Event has an invalid origin server name: {e}"))))?; .map_err(|e| err!(Request(BadJson("Event has an invalid origin server name: {e}"))))?;
trace!("Signing send_join event");
services
.server_keys
.hash_and_sign_event(&mut value, &room_version_id)
.map_err(|e| err!(Request(InvalidParam(warn!("Failed to sign send_join event: {e}")))))?;
let mutex_lock = services let mutex_lock = services
.rooms .rooms
.event_handler .event_handler
@ -204,7 +200,7 @@ async fn create_join_event(
.lock(room_id) .lock(room_id)
.await; .await;
debug!("Acquired send_join mutex, persisting join event"); trace!("Acquired send_join mutex, persisting join event");
let pdu_id = services let pdu_id = services
.rooms .rooms
.event_handler .event_handler
@ -214,7 +210,7 @@ async fn create_join_event(
.ok_or_else(|| err!(Request(InvalidParam("Could not accept as timeline event."))))?; .ok_or_else(|| err!(Request(InvalidParam("Could not accept as timeline event."))))?;
drop(mutex_lock); drop(mutex_lock);
debug!("Fetching current state IDs"); trace!("Fetching current state IDs");
let state_ids: Vec<OwnedEventId> = services let state_ids: Vec<OwnedEventId> = services
.rooms .rooms
.state_accessor .state_accessor
@ -223,21 +219,19 @@ async fn create_join_event(
.collect() .collect()
.await; .await;
#[allow(clippy::unnecessary_unwrap)] trace!(%omit_members, "Constructing current state");
let state = state_ids let state = state_ids
.iter() .iter()
.try_stream() .try_stream()
.broad_filter_map(|event_id| async move { .broad_filter_map(|event_id| async move {
if omit_members && event_id.is_ok() { if omit_members {
let pdu = services if let Ok(e) = event_id.as_ref() {
.rooms let pdu = services.rooms.timeline.get_pdu(e).await;
.timeline if pdu.is_ok_and(|p| p.kind().to_cow_str() == "m.room.member") {
.get_pdu(event_id.as_ref().unwrap()) trace!("omitting member event {e:?} from returned state");
.await; // skip members
if pdu.is_ok_and(|p| p.kind().to_cow_str() == "m.room.member") { return None;
trace!("omitting member event {event_id:?} from returned state"); }
// skip members
return None;
} }
} }
Some(event_id) Some(event_id)
@ -254,21 +248,11 @@ async fn create_join_event(
.await?; .await?;
let starting_events = state_ids.iter().map(Borrow::borrow); let starting_events = state_ids.iter().map(Borrow::borrow);
trace!("Constructing auth chain");
let auth_chain = services let auth_chain = services
.rooms .rooms
.auth_chain .auth_chain
.event_ids_iter(room_id, starting_events) .event_ids_iter(room_id, starting_events)
// .broad_filter_map(|event_id| async {
// if omit_members && event_id.as_ref().is_ok_and(|e| state_ids.contains(e)) {
// // Don't include this event if it's already in the state
// trace!(
// "omitting member event {event_id:?} from returned auth chain as it is \
// already in state"
// );
// return None;
// }
// Some(event_id)
// })
.broad_and_then(|event_id| async move { .broad_and_then(|event_id| async move {
services.rooms.timeline.get_pdu_json(&event_id).await services.rooms.timeline.get_pdu_json(&event_id).await
}) })
@ -281,12 +265,13 @@ async fn create_join_event(
.try_collect() .try_collect()
.boxed() .boxed()
.await?; .await?;
info!(fast_join = %omit_members, "Sending join event to other servers");
services.sending.send_pdu_room(room_id, &pdu_id).await?; services.sending.send_pdu_room(room_id, &pdu_id).await?;
debug!("Finished sending join event");
let servers_in_room: Option<Vec<_>> = if !omit_members { let servers_in_room: Option<Vec<_>> = if !omit_members {
None None
} else { } else {
debug!("Fetching list of servers in room"); trace!("Fetching list of servers in room");
let servers: Vec<String> = services let servers: Vec<String> = services
.rooms .rooms
.state_cache .state_cache
@ -296,8 +281,10 @@ async fn create_join_event(
.await; .await;
// If there's no servers, just add us // If there's no servers, just add us
let servers = if servers.is_empty() { let servers = if servers.is_empty() {
warn!("Failed to find any servers, adding our own server name as a last resort");
vec![services.globals.server_name().to_string()] vec![services.globals.server_name().to_string()]
} else { } else {
trace!("Found {} servers in room", servers.len());
servers servers
}; };
Some(servers) Some(servers)
@ -346,7 +333,6 @@ pub(crate) async fn create_join_event_v1_route(
} }
} }
info!("Providing send_join for {} in {}", body.origin(), &body.room_id);
let now = Instant::now(); let now = Instant::now();
let room_state = create_join_event(&services, body.origin(), &body.room_id, &body.pdu, false) let room_state = create_join_event(&services, body.origin(), &body.room_id, &body.pdu, false)
.boxed() .boxed()
@ -357,7 +343,7 @@ pub(crate) async fn create_join_event_v1_route(
event: room_state.event, event: room_state.event,
}; };
info!( info!(
"Finished creating the send_join payload for {} in {} in {:?}", "Finished sending a join for {} in {} in {:?}",
body.origin(), body.origin(),
&body.room_id, &body.room_id,
now.elapsed() now.elapsed()
@ -394,14 +380,13 @@ pub(crate) async fn create_join_event_v2_route(
} }
} }
info!("Providing send_join for {} in {}", body.origin(), &body.room_id);
let now = Instant::now(); let now = Instant::now();
let room_state = let room_state =
create_join_event(&services, body.origin(), &body.room_id, &body.pdu, body.omit_members) create_join_event(&services, body.origin(), &body.room_id, &body.pdu, body.omit_members)
.boxed() .boxed()
.await?; .await?;
info!( info!(
"Finished creating the send_join payload for {} in {} in {:?}", "Finished sending a join for {} in {} in {:?}",
body.origin(), body.origin(),
&body.room_id, &body.room_id,
now.elapsed() now.elapsed()