Struct FinamRaw
pub struct FinamRaw { /* private fields */ }Expand description
Handle for calling any Finam method with the connector’s token, endpoint and rate limiter.
Get it from MarketDataConnector::raw or UserDataConnector::raw. Cheap to clone. It stays
usable while the connector it came from is alive. See the module docs for the rules of a call.
§Examples
A command goes through call_command, a read through call:
use brokapi_core::Error;
use brokapi_finam::limits::default_limits;
use brokapi_finam::{UserDataConfig, UserDataConnector};
use brokapi_runtime::BrokerLimiter;
use brokapi_finam_protocol::pb::grpc::tradeapi::v1::accounts::GetAccountRequest;
use tokio::sync::mpsc;
let (events, _rx) = mpsc::channel(16);
let ud = UserDataConnector::start(
UserDataConfig::new(api, "ACC1", "finam-ud"),
BrokerLimiter::new(&default_limits()),
events,
)
.await?;
let raw = ud.raw();
assert_eq!(raw.account_id(), Some("ACC1"));
let account = raw
.call("GetAccount", |api| async move {
api.accounts().get_account(GetAccountRequest { account_id: "ACC1".into() }).await
})
.await?;
assert_eq!(account.account_id, "ACC1");
// An account the broker does not know is a refusal.
let err = raw
.call("GetAccount", |api| async move {
api.accounts().get_account(GetAccountRequest { account_id: "NOPE".into() }).await
})
.await
.unwrap_err();
assert!(matches!(err, Error::Rejected { .. }));Implementations§
§impl FinamRaw
impl FinamRaw
pub fn account_id(&self) -> Option<&str>
pub fn account_id(&self) -> Option<&str>
Account of the connector this came from. None for a market data connector.
pub fn timeout(&self) -> Duration
pub fn timeout(&self) -> Duration
Deadline applied to every call (FinamApiConfig::request_timeout of the connector).
pub async fn call<T, F, Fut>(&self, method: &str, f: F) -> Result<T, Error>
pub async fn call<T, F, Fut>(&self, method: &str, f: F) -> Result<T, Error>
Reads: quota for method, deadline, one re-auth retry, error mapping.
f may run twice (after a re-auth), hence Fn. For a server-streaming method the result is
tonic::Streaming<_>: the quota covers opening the stream. A stream opened here is not
supervised: when it breaks or the token changes, open it again yourself.
Do not use it for a call that changes the account, because of the repeat. Use
call_command.
§Errors
- [
Error::RateLimited]: the local quota formethodis spent. Nothing was sent. - [
Error::Rejected]: the broker refused (bad argument, unknown id, no permission, or the token was refused again after the renewal). - [
Error::Transport]: connection failure, or no answer withintimeout.
A failed token renewal is reported with the same mapping.
§Examples
See the module docs.
pub async fn call_command<T, F, Fut>(
&self,
method: &str,
f: F,
) -> Result<T, Error>
pub async fn call_command<T, F, Fut>( &self, method: &str, f: F, ) -> Result<T, Error>
Commands: quota for method, deadline, NO retry. Anything that may have reached the broker
(timeout, break, server fault) is Error::Unknown.
There is no repeat on purpose: a second send could change the account twice. When the answer
is Unknown, read the state (orders, positions) before deciding anything.
The order index of the connector does not see what you place here: no events, no
reconcile. For plain and stop orders use the shared traits.
§Errors
- [
Error::RateLimited]: the local quota formethodis spent. Nothing was sent. - [
Error::Rejected]: the broker certainly did not process the request (for exampleINVALID_ARGUMENTorNOT_FOUND, which is the codenot_found). - [
Error::Config]:UNAUTHENTICATED, the token is refused. A command is not repeated after a token renewal. - [
Error::Unknown]: timeout, broken connection or server fault. The command may have been applied.
§Examples
use brokapi_core::Error;
use brokapi_finam::limits::default_limits;
use brokapi_finam::{MarketDataConfig, MarketDataConnector};
use brokapi_runtime::BrokerLimiter;
use brokapi_finam_protocol::pb::grpc::tradeapi::v1::marketdata::QuoteRequest;
use tokio::sync::mpsc;
// Same shape as a read, but never repeated. The result of a real command is handled the same way.
let sent = md
.raw()
.call_command("LastQuote", |api| async move {
api.market_data().last_quote(QuoteRequest { symbol: "SBER@MISX".into() }).await
})
.await;
match sent {
Ok(reply) => assert_eq!(reply.symbol, "SBER@MISX"),
Err(Error::Unknown) => { /* read the state before acting */ }
Err(other) => panic!("refused: {other}"),
}Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for FinamRaw
impl !UnwindSafe for FinamRaw
impl Freeze for FinamRaw
impl Send for FinamRaw
impl Sync for FinamRaw
impl Unpin for FinamRaw
impl UnsafeUnpin for FinamRaw
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].