rocketmq_client_rust/session.rs
1// Copyright 2026 The RocketMQ Rust Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Shared ownership boundary for client capabilities.
16
17use std::fmt;
18use std::sync::Arc;
19
20use crate::runtime::ClientRuntime;
21
22/// Identifies the application-owned runtime and task owner shared by a set of
23/// client capabilities.
24///
25/// Cloning a session only clones the runtime `Arc`; it does not create a
26/// runtime, connection pool, route cache, or background task.
27#[derive(Clone)]
28pub struct ClientSession {
29 runtime: Arc<ClientRuntime>,
30}
31
32impl ClientSession {
33 #[must_use]
34 pub fn new(runtime: Arc<ClientRuntime>) -> Self {
35 Self { runtime }
36 }
37
38 /// Returns the shared application runtime.
39 #[must_use]
40 pub fn runtime(&self) -> Arc<ClientRuntime> {
41 Arc::clone(&self.runtime)
42 }
43
44 /// Returns whether both handles are backed by the same runtime and task
45 /// owner.
46 #[must_use]
47 pub fn shares_runtime_with(&self, other: &Self) -> bool {
48 Arc::ptr_eq(&self.runtime, &other.runtime)
49 }
50}
51
52impl fmt::Debug for ClientSession {
53 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
54 formatter
55 .debug_struct("ClientSession")
56 .field("runtime", &"<shared>")
57 .finish()
58 }
59}
60
61/// Implemented by concrete client handles that borrow one shared session.
62///
63/// Publicly constructed handles always return `Some`. `None` is reserved for
64/// crate-internal bootstrap producers that are owned directly by a
65/// [`rocketmq_runtime::ChildServiceContext`] instead of a public client session.
66pub trait ClientSessionProvider {
67 #[must_use]
68 fn client_session(&self) -> Option<&ClientSession>;
69}
70
71#[cfg(test)]
72mod tests {
73 use super::ClientSession;
74 use crate::runtime::test_client_runtime;
75
76 #[test]
77 fn cloning_session_preserves_runtime_identity() {
78 let session = ClientSession::new(test_client_runtime("client-session-identity"));
79 let clone = session.clone();
80
81 assert!(session.shares_runtime_with(&clone));
82 }
83}