2023-06-05 21:17:07 +00:00
|
|
|
use std::{
|
|
|
|
|
fs,
|
|
|
|
|
io::{BufWriter, Write},
|
2023-10-30 01:31:41 +00:00
|
|
|
time::Duration,
|
2023-06-05 21:17:07 +00:00
|
|
|
};
|
|
|
|
|
|
2023-05-30 22:44:29 +00:00
|
|
|
use chrono::Utc;
|
|
|
|
|
use lazy_static::lazy_static;
|
|
|
|
|
use serde::Serialize;
|
2023-10-30 01:31:41 +00:00
|
|
|
use tokio::{
|
|
|
|
|
sync::mpsc::{unbounded_channel, UnboundedSender},
|
|
|
|
|
time::{self},
|
|
|
|
|
};
|
2023-05-30 22:44:29 +00:00
|
|
|
|
|
|
|
|
lazy_static! {
|
2023-10-30 01:31:41 +00:00
|
|
|
static ref WRITER: UnboundedSender<String> = {
|
|
|
|
|
let (tx, mut rx) = unbounded_channel::<String>();
|
|
|
|
|
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
|
let events_dir = crate::path::events_dir();
|
|
|
|
|
std::fs::create_dir_all(events_dir.as_path()).ok();
|
|
|
|
|
|
|
|
|
|
let now = Utc::now();
|
|
|
|
|
let fname = now.format("%Y-%m-%d.json");
|
|
|
|
|
let file = fs::OpenOptions::new()
|
|
|
|
|
.create(true)
|
|
|
|
|
.append(true)
|
|
|
|
|
.write(true)
|
|
|
|
|
.open(events_dir.join(fname.to_string()))
|
|
|
|
|
.ok()
|
|
|
|
|
.unwrap();
|
2023-05-30 22:44:29 +00:00
|
|
|
|
2023-10-30 01:31:41 +00:00
|
|
|
let mut writer = BufWriter::new(file);
|
|
|
|
|
let mut interval = time::interval(Duration::from_secs(5));
|
2023-05-30 22:44:29 +00:00
|
|
|
|
2023-10-30 01:31:41 +00:00
|
|
|
loop {
|
|
|
|
|
tokio::select! {
|
|
|
|
|
content = rx.recv() => {
|
|
|
|
|
if let Some(content) = content {
|
|
|
|
|
writeln!(&mut writer, "{}", content).unwrap();
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ = interval.tick() => {
|
|
|
|
|
writer.flush().unwrap();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
tx
|
2023-05-30 22:44:29 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize)]
|
|
|
|
|
pub struct Choice<'a> {
|
|
|
|
|
pub index: u32,
|
|
|
|
|
pub text: &'a str,
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-16 08:02:40 +00:00
|
|
|
#[derive(Serialize)]
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
pub enum SelectKind {
|
|
|
|
|
Line,
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-30 22:44:29 +00:00
|
|
|
#[derive(Serialize)]
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
pub enum Event<'a> {
|
|
|
|
|
View {
|
|
|
|
|
completion_id: &'a str,
|
|
|
|
|
choice_index: u32,
|
|
|
|
|
},
|
2023-05-31 00:12:10 +00:00
|
|
|
Select {
|
2023-05-30 22:44:29 +00:00
|
|
|
completion_id: &'a str,
|
|
|
|
|
choice_index: u32,
|
2023-07-16 08:02:40 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
|
kind: Option<SelectKind>,
|
2023-05-30 22:44:29 +00:00
|
|
|
},
|
|
|
|
|
Completion {
|
|
|
|
|
completion_id: &'a str,
|
|
|
|
|
language: &'a str,
|
|
|
|
|
prompt: &'a str,
|
2023-10-21 20:47:44 +00:00
|
|
|
segments: &'a Option<Segments>,
|
2023-05-30 22:44:29 +00:00
|
|
|
choices: Vec<Choice<'a>>,
|
2023-06-14 17:49:31 +00:00
|
|
|
user: Option<&'a str>,
|
2023-05-30 22:44:29 +00:00
|
|
|
},
|
|
|
|
|
}
|
2023-10-13 02:27:52 +00:00
|
|
|
#[derive(Serialize)]
|
2023-10-21 20:47:44 +00:00
|
|
|
pub struct Segments {
|
|
|
|
|
pub prefix: String,
|
|
|
|
|
pub suffix: Option<String>,
|
2023-10-13 02:27:52 +00:00
|
|
|
}
|
2023-05-30 22:44:29 +00:00
|
|
|
|
|
|
|
|
#[derive(Serialize)]
|
|
|
|
|
struct Log<'a> {
|
|
|
|
|
ts: u128,
|
|
|
|
|
event: &'a Event<'a>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Event<'_> {
|
|
|
|
|
pub fn log(&self) {
|
2023-10-30 01:31:41 +00:00
|
|
|
let content = serdeconv::to_json_string(&Log {
|
|
|
|
|
ts: timestamp(),
|
|
|
|
|
event: self,
|
|
|
|
|
})
|
2023-05-30 22:44:29 +00:00
|
|
|
.unwrap();
|
2023-10-30 01:31:41 +00:00
|
|
|
|
|
|
|
|
WRITER.send(content).unwrap();
|
2023-05-30 22:44:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn timestamp() -> u128 {
|
|
|
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
|
|
|
let start = SystemTime::now();
|
|
|
|
|
start
|
|
|
|
|
.duration_since(UNIX_EPOCH)
|
|
|
|
|
.expect("Time went backwards")
|
|
|
|
|
.as_millis()
|
|
|
|
|
}
|