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(
53 &self,
54 category: CalendarCategory,
55 start: impl Into<String>,
56 end: impl Into<String>,
57 market: Option<String>,
58 ) -> Result<CalendarEventsResponse> {
59 let cat_str = match category {
60 CalendarCategory::Report => "report",
61 CalendarCategory::Dividend => "dividend",
62 CalendarCategory::Split => "split",
63 CalendarCategory::Ipo => "ipo",
64 CalendarCategory::MacroData => "macrodata",
65 CalendarCategory::Closed => "closed",
66 CalendarCategory::Meeting => "meeting",
67 CalendarCategory::Merge => "merge",
68 };
69 #[derive(Serialize)]
70 struct Query {
71 date: String,
72 date_end: String,
73 #[serde(rename = "types[]")]
74 types: &'static str,
75 #[serde(rename = "markets[]", skip_serializing_if = "Option::is_none")]
76 markets: Option<String>,
77 }
78 Ok(self
79 .0
80 .http_cli
81 .request(Method::GET, "/v1/quote/finance_calendar")
82 .query_params(Query {
83 date: start.into(),
84 date_end: end.into(),
85 types: cat_str,
86 markets: market,
87 })
88 .response::<Json<CalendarEventsResponse>>()
89 .send()
90 .with_subscriber(self.0.log_subscriber.clone())
91 .await?
92 .0)
93 }
94}