Skip to content

Commit 98f0d68

Browse files
authored
feat: added API to fetch a single event by ID (#268)
1 parent 28cdcac commit 98f0d68

File tree

6 files changed

+127
-1
lines changed

6 files changed

+127
-1
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ jobs:
7373
rustup component add llvm-tools-preview
7474
- name: Download grcov
7575
run: |
76-
curl -L https://github.com/mozilla/grcov/releases/latest/download/grcov-linux-x86_64.tar.bz2 | tar jxf -
76+
curl -L https://github.com/mozilla/grcov/releases/latest/download/grcov-x86_64-unknown-linux-gnu.tar.bz2 | tar jxf -
7777
- name: Run tests with coverage
7878
run: |
7979
# Add cwd to path to find grcov

aw-datastore/src/datastore.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,67 @@ impl DatastoreInstance {
662662
Ok(inserted_heartbeat)
663663
}
664664

665+
pub fn get_event(
666+
&mut self,
667+
conn: &Connection,
668+
bucket_id: &str,
669+
event_id: i64,
670+
) -> Result<Event, DatastoreError> {
671+
let bucket = self.get_bucket(bucket_id)?;
672+
673+
let mut stmt = match conn.prepare(
674+
"
675+
SELECT id, starttime, endtime, data
676+
FROM events
677+
WHERE bucketrow = ?1
678+
AND id = ?2
679+
LIMIT 1
680+
;",
681+
) {
682+
Ok(stmt) => stmt,
683+
Err(err) => {
684+
return Err(DatastoreError::InternalError(format!(
685+
"Failed to prepare get_event SQL statement: {}",
686+
err
687+
)))
688+
}
689+
};
690+
691+
// TODO: Refactor to share row-parsing logic with get_events
692+
let row = match stmt.query_row(&[&bucket.bid.unwrap(), &event_id], |row| {
693+
let id = row.get(0)?;
694+
let starttime_ns: i64 = row.get(1)?;
695+
let endtime_ns: i64 = row.get(2)?;
696+
let data_str: String = row.get(3)?;
697+
698+
let time_seconds: i64 = (starttime_ns / 1_000_000_000) as i64;
699+
let time_subnanos: u32 = (starttime_ns % 1_000_000_000) as u32;
700+
let duration_ns = endtime_ns - starttime_ns;
701+
let data: serde_json::map::Map<String, Value> =
702+
serde_json::from_str(&data_str).unwrap();
703+
704+
Ok(Event {
705+
id: Some(id),
706+
timestamp: DateTime::<Utc>::from_utc(
707+
NaiveDateTime::from_timestamp(time_seconds, time_subnanos),
708+
Utc,
709+
),
710+
duration: Duration::nanoseconds(duration_ns),
711+
data,
712+
})
713+
}) {
714+
Ok(rows) => rows,
715+
Err(err) => {
716+
return Err(DatastoreError::InternalError(format!(
717+
"Failed to map get_event SQL statement: {}",
718+
err
719+
)))
720+
}
721+
};
722+
723+
Ok(row)
724+
}
725+
665726
pub fn get_events(
666727
&mut self,
667728
conn: &Connection,

aw-datastore/src/worker.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ pub enum Command {
6464
GetBuckets(),
6565
InsertEvents(String, Vec<Event>),
6666
Heartbeat(String, Event, f64),
67+
GetEvent(String, i64),
6768
GetEvents(
6869
String,
6970
Option<DateTime<Utc>>,
@@ -241,6 +242,12 @@ impl DatastoreWorker {
241242
Err(e) => Err(e),
242243
}
243244
}
245+
Command::GetEvent(bucketname, event_id) => {
246+
match ds.get_event(&transaction, &bucketname, event_id) {
247+
Ok(el) => Ok(Response::Event(el)),
248+
Err(e) => Err(e),
249+
}
250+
}
244251
Command::GetEvents(bucketname, starttime_opt, endtime_opt, limit_opt) => {
245252
match ds.get_events(
246253
&transaction,
@@ -395,6 +402,18 @@ impl Datastore {
395402
}
396403
}
397404

405+
pub fn get_event(&self, bucket_id: &str, event_id: i64) -> Result<Event, DatastoreError> {
406+
let cmd = Command::GetEvent(bucket_id.to_string(), event_id);
407+
let receiver = self.requester.request(cmd).unwrap();
408+
match receiver.collect().unwrap() {
409+
Ok(r) => match r {
410+
Response::Event(el) => Ok(el),
411+
_ => panic!("Invalid response"),
412+
},
413+
Err(e) => Err(e),
414+
}
415+
}
416+
398417
pub fn get_events(
399418
&self,
400419
bucket_id: &str,

aw-datastore/tests/datastore.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,34 @@ mod datastore_tests {
121121
}
122122
}
123123

124+
#[test]
125+
fn test_events_get_single() {
126+
// Setup datastore
127+
let ds = Datastore::new_in_memory(false);
128+
let bucket = create_test_bucket(&ds);
129+
130+
// Insert event
131+
let e1 = Event {
132+
id: None,
133+
timestamp: Utc::now(),
134+
duration: Duration::seconds(0),
135+
data: json_map! {"key": json!("value")},
136+
};
137+
let mut e2 = e1.clone();
138+
e2.timestamp = e2.timestamp + Duration::nanoseconds(1);
139+
140+
let event_list = [e1.clone(), e2.clone()];
141+
ds.insert_events(&bucket.id, &event_list).unwrap();
142+
143+
let events = ds.get_events(&bucket.id, None, None, None).unwrap();
144+
let first_event = events.first().unwrap();
145+
let first_event_id = first_event.id.unwrap();
146+
147+
let fetched_event = ds.get_event(&bucket.id, first_event_id).unwrap();
148+
// TODO: Check entire events to ensure integrity
149+
assert_eq!(fetched_event.id.unwrap(), first_event_id);
150+
}
151+
124152
#[test]
125153
fn test_events_get_filters() {
126154
// Setup datastore

aw-server/src/endpoints/bucket.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,23 @@ pub fn bucket_events_get(
101101
}
102102
}
103103

104+
// Needs unused parameter, otherwise there'll be a route collision
105+
// See: https://api.rocket.rs/master/rocket/struct.Route.html#resolving-collisions
106+
#[get("/<bucket_id>/events/<event_id>?<_unused..>")]
107+
pub fn bucket_events_get_single(
108+
bucket_id: String,
109+
event_id: i64,
110+
_unused: Option<u64>,
111+
state: &State<ServerState>,
112+
) -> Result<Json<Event>, HttpErrorJson> {
113+
let datastore = endpoints_get_lock!(state.datastore);
114+
let res = datastore.get_event(&bucket_id, event_id);
115+
match res {
116+
Ok(events) => Ok(Json(events)),
117+
Err(err) => Err(err.into()),
118+
}
119+
}
120+
104121
#[post("/<bucket_id>/events", data = "<events>", format = "application/json")]
105122
pub fn bucket_events_create(
106123
bucket_id: String,

aw-server/src/endpoints/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ pub fn build_rocket(server_state: ServerState, config: AWConfig) -> rocket::Rock
121121
bucket::bucket_events_create,
122122
bucket::bucket_events_heartbeat,
123123
bucket::bucket_event_count,
124+
bucket::bucket_events_get_single,
124125
bucket::bucket_events_delete_by_id,
125126
bucket::bucket_export
126127
],

0 commit comments

Comments
 (0)