Skip to main content

grammers_session/
session.rs

1// Copyright 2020 - developers of the `grammers` project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use crate::BoxFuture;
10use crate::peer::PeerRef;
11use crate::types::{DcOption, PeerId, PeerInfo, UpdateState, UpdatesState};
12
13/// The main interface to interact with the different [`crate::storages`].
14///
15/// All methods are synchronous and currently infallible because clients
16/// are not equipped to deal with the arbitrary errors that a dynamic
17/// `Session` could produce. This may change in the future.
18///
19/// A newly-created storage should return the same values that
20/// [crate::SessionData::default] would produce.
21pub trait Session: Send + Sync + 'static {
22    type Error: Send;
23
24    /// Datacenter that is "home" to the user authorized by this session.
25    ///
26    /// If not known, the ID of the closest datacenter should be returned instead.
27    /// Note that incorrect guesses are allowed, and the user may need to migrate.
28    ///
29    /// Note that it is used on every request and thus should be cheap to call.
30    fn home_dc_id(&self) -> Result<i32, Self::Error>;
31
32    /// Changes the [`Session::home_dc_id`] after finding out the actual datacenter
33    /// to which main queries should be executed against.
34    ///
35    /// This must update the value in the cache layer used by `home_dc_id`.
36    fn set_home_dc_id(&self, dc_id: i32) -> BoxFuture<'_, Result<(), Self::Error>>;
37
38    /// Query a single datacenter option.
39    ///
40    /// If no up-to-date option has been [`Session::set_dc_option`] yet,
41    /// a statically-known option must be returned.
42    ///
43    /// `None` may only be returned on invalid DC IDs or DCs that are not yet known.
44    ///
45    /// Note that it is used on every request and thus should be cheap to call.
46    fn dc_option(&self, dc_id: i32) -> Result<Option<DcOption>, Self::Error>;
47
48    /// Update the previously-known [`Session::dc_option`] with new values.
49    ///
50    /// Should also be used after generating permanent authentication keys to a datacenter.
51    ///
52    /// This must update the value in the cache layer used by `dc_option`.
53    fn set_dc_option(&self, dc_option: &DcOption) -> BoxFuture<'_, Result<(), Self::Error>>;
54
55    /// Query a peer by its identity.
56    ///
57    /// Querying for [`PeerId::self_user`] can be used as a way to determine
58    /// whether the authentication key has a logged-in user bound (i.e. signed in).
59    fn peer(&self, peer: PeerId) -> BoxFuture<'_, Result<Option<PeerInfo>, Self::Error>>;
60
61    /// Query the full peer reference from its identity.
62    ///
63    /// By default, this uses [`Session::peer`] to retrieve the [`PeerAuth`](crate::types::PeerAuth).
64    ///
65    /// If you want to obtain a `PeerRef` from a `PeerId` regardless of whether it is cached
66    /// in the session or not, you can pair this method with [`PeerId::to_ambient_ref`].
67    fn peer_ref(&self, peer: PeerId) -> BoxFuture<'_, Result<Option<PeerRef>, Self::Error>> {
68        Box::pin(async move {
69            Ok(self
70                .peer(peer)
71                .await?
72                .and_then(|info| info.auth())
73                .map(|auth| PeerRef { id: peer, auth }))
74        })
75    }
76
77    /// Cache a peer's basic information for [`Session::peer`] to be able to query them later.
78    ///
79    /// This method may not necessarily remember the peers forever,
80    /// except for users where [`PeerInfo::User::is_self`] is `Some(true)`.
81    fn cache_peer(&self, peer: PeerInfo) -> BoxFuture<'_, Result<(), Self::Error>>;
82
83    /// Bulk cache_peer, allows optimization in specific implementations
84    fn cache_peers(&self, peers: Vec<PeerInfo>) -> BoxFuture<'_, Result<(), Self::Error>> {
85        Box::pin(async move {
86            let mut result = Ok(());
87            for peer in peers {
88                if let Err(e) = self.cache_peer(peer).await {
89                    result = Err(e);
90                }
91            }
92            result
93        })
94    }
95
96    /// Loads the entire updates state.
97    fn updates_state(&self) -> BoxFuture<'_, Result<UpdatesState, Self::Error>>;
98
99    /// Update the state for one or all updates.
100    fn set_update_state(&self, update: UpdateState) -> BoxFuture<'_, Result<(), Self::Error>>;
101}