longbridge/calendar/
context.rs1use std::sync::Arc;
2
3use longbridge_httpcli::{HttpClient, Json, Method};
4use serde::Serialize;
5use tracing::{Subscriber, dispatcher, instrument::WithSubscriber};
6
7use crate::{Config, Result, calendar::types::*};
8
9struct InnerCalendarContext {
10 http_cli: HttpClient,
11 log_subscriber: Arc<dyn Subscriber + Send + Sync>,
12}
13
14impl Drop for InnerCalendarContext {
15 fn drop(&mut self) {
16 dispatcher::with_default(&self.log_subscriber.clone().into(), || {
17 tracing::info!("calendar context dropped");
18 });
19 }
20}
21
22#[derive(Clone)]
24pub struct CalendarContext(Arc<InnerCalendarContext>);
25
26impl CalendarContext {
27 pub fn new(config: Arc<Config>) -> Self {
29 let log_subscriber = config.create_log_subscriber("calendar");
30 dispatcher::with_default(&log_subscriber.clone().into(), || {
31 tracing::info!(language = ?config.language, "creating calendar context");
32 });
33 let ctx = Self(Arc::new(InnerCalendarContext {
34 http_cli: config.create_http_client(),
35 log_subscriber,
36 }));
37 dispatcher::with_default(&ctx.0.log_subscriber.clone().into(), || {
38 tracing::info!("calendar context created");
39 });
40 ctx
41 }
42
43 #[inline]
45 pub fn log_subscriber(&self) -> Arc<dyn Subscriber + Send + Sync> {
46 self.0.log_subscriber.clone()
47 }
48
49 pub async fn finance_calendar(
56 &self,
57 category: CalendarCategory,
58 start: impl Into<String>,
59 end: impl Into<String>,
60 market: Option<String>,
61 ) -> Result<CalendarEventsResponse> {
62 let cat_str = match category {
63 CalendarCategory::Report => "report",
64 CalendarCategory::Dividend => "dividend",
65 CalendarCategory::Split => "split",
66 CalendarCategory::Ipo => "ipo",
67 CalendarCategory::MacroData => "macrodata",
68 CalendarCategory::Closed => "closed",
69 CalendarCategory::Meeting => "meeting",
70 CalendarCategory::Merge => "merge",
71 };
72 #[derive(Serialize)]
73 struct Query {
74 date: String,
75 date_end: String,
76 #[serde(rename = "types[]")]
77 types: &'static str,
78 #[serde(rename = "markets[]", skip_serializing_if = "Option::is_none")]
79 markets: Option<String>,
80 }
81 Ok(self
82 .0
83 .http_cli
84 .request(Method::GET, "/v1/quote/finance_calendar")
85 .query_params(Query {
86 date: start.into(),
87 date_end: end.into(),
88 types: cat_str,
89 markets: market,
90 })
91 .response::<Json<CalendarEventsResponse>>()
92 .send()
93 .with_subscriber(self.0.log_subscriber.clone())
94 .await?
95 .0)
96 }
97}