agent_client_protocol/jsonrpc/
close.rs1use std::fmt::Debug;
4use std::future::Future;
5use std::marker::PhantomData;
6
7use crate::{
8 ConnectionTo,
9 jsonrpc::{ConnectionContext, RawConnectionContext, connection_context},
10 role::Role,
11};
12
13pub trait HandleConnectionClose<Counterpart: Role>: Send {
20 fn handle_connection_close(
22 self,
23 connection: ConnectionTo<Counterpart>,
24 ) -> impl Future<Output = Result<(), crate::Error>> + Send;
25}
26
27#[derive(Debug, Default)]
29pub struct NullClose;
30
31impl<Counterpart: Role> HandleConnectionClose<Counterpart> for NullClose {
32 fn handle_connection_close(
33 self,
34 _connection: ConnectionTo<Counterpart>,
35 ) -> impl Future<Output = Result<(), crate::Error>> + Send {
36 std::future::ready(Ok(()))
37 }
38}
39
40pub(crate) struct CloseCallback<F, Context = RawConnectionContext> {
41 callback: F,
42 context: PhantomData<fn() -> Context>,
43}
44
45impl<F, Context> CloseCallback<F, Context> {
46 pub(crate) fn new(callback: F) -> Self {
47 Self {
48 callback,
49 context: PhantomData,
50 }
51 }
52}
53
54impl<F, Context> Debug for CloseCallback<F, Context> {
55 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 formatter
57 .debug_struct("CloseCallback")
58 .finish_non_exhaustive()
59 }
60}
61
62impl<Counterpart, F, Fut, Context> HandleConnectionClose<Counterpart> for CloseCallback<F, Context>
63where
64 Counterpart: Role,
65 Context: ConnectionContext,
66 F: FnOnce(Context::Connection<Counterpart>) -> Fut + Send,
67 Fut: Future<Output = Result<(), crate::Error>> + Send,
68{
69 async fn handle_connection_close(
70 self,
71 connection: ConnectionTo<Counterpart>,
72 ) -> Result<(), crate::Error> {
73 let result = (self.callback)(connection_context::from_raw::<Context, _>(connection)).await;
74 if let Err(error) = &result {
75 tracing::warn!(?error, "Connection close callback failed");
76 }
77 result
78 }
79}
80
81#[derive(Debug)]
82pub(crate) struct ChainedClose<A, B> {
83 first: A,
84 second: B,
85}
86
87impl<A, B> ChainedClose<A, B> {
88 pub(crate) fn new(first: A, second: B) -> Self {
89 Self { first, second }
90 }
91}
92
93impl<Counterpart, A, B> HandleConnectionClose<Counterpart> for ChainedClose<A, B>
94where
95 Counterpart: Role,
96 A: HandleConnectionClose<Counterpart>,
97 B: HandleConnectionClose<Counterpart>,
98{
99 async fn handle_connection_close(
100 self,
101 connection: ConnectionTo<Counterpart>,
102 ) -> Result<(), crate::Error> {
103 let first = Box::pin(self.first.handle_connection_close(connection.clone())).await;
106 let second = Box::pin(self.second.handle_connection_close(connection)).await;
107 first.and(second)
108 }
109}