Skip to content

Commit

Permalink
Merge pull request #22 from Holo-Host/list_available_update
Browse files Browse the repository at this point in the history
list_available takes hours not days
  • Loading branch information
Alastair Ong authored Feb 20, 2023
2 parents 0539c9c + 45c54db commit 6a0805d
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 43 deletions.
40 changes: 13 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@ Public API for collecting and reading statistics on holoports and holo network

Endpoints:

#### GET `/`
### GET `/`

Gets status of connection to db.

#### `200 OK`

Text: status of connection to db
### DELETE `/cleanup`

Deletes from host_statistics.holoport_status documents with timestamp field older than 30 days.

#### `200 OK`

GET
`/hosts/list-available?days=7`
### GET `/hosts/list-available?hours=7`

days = Cut off time. Records older than this will be ignored.
hours = Cut off time. Records older than this will be ignored.

This endpoint returns all the holoports on the holo network as seen by both zerotier network controller and Holoport's netstatsd. Data from both sources is merged and analyzed for possible errors. All the errors are reported in form of an array under field `errors`.

Expand All @@ -39,24 +44,7 @@ This endpoint returns all the holoports on the holo network as seen by both zero
]
```

GET
`/hosts/registered?days=7`

days = Cut off time. Records older than this will be ignored.

#### `200 OK`

```json
[
"holoport_id_1",
"holoport_id_2",
"holoport_id_3",
"holoport_id_4"
]
```

GET
`/hosts/<name>/uptime`
### GET `/hosts/<name>/uptime`

#### `200 OK`

Expand All @@ -66,8 +54,7 @@ GET
}
```

GET
`/network/capacity`
### GET `/network/capacity`

#### `200 OK`

Expand All @@ -79,8 +66,7 @@ GET
}
```

POST
`/hosts/stats`
### POST `/hosts/stats`

payload:
```json
Expand Down
23 changes: 11 additions & 12 deletions src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use crate::types::{
Uptime, ZerotierMember,
};

const DAYS_TOO_LARGE: Error400 =
Error400::Message("Days specified is too large. Cutoff is earlier than start of unix epoch");
const HOURS_TOO_LARGE: Error400 =
Error400::Message("Hours specified is too large. Cutoff is earlier than start of unix epoch");

// AppDbPool is managed by Rocket as a State, which means it is available across threads.
// Type mongodb::Database (starting v2.0.0 of mongodb driver) represents a connection pool to db,
Expand Down Expand Up @@ -50,9 +50,9 @@ pub async fn cleanup_database(db: &Client) -> Result<String, ApiError> {
let hp_status: Collection<HostStats> =
db.database("host_statistics").collection("holoport_status");

let cutoff_ms = match get_cutoff_timestamp(30) {
let cutoff_ms = match get_cutoff_timestamp(30 * 24) {
Some(x) => x,
None => return Err(ApiError::BadRequest(DAYS_TOO_LARGE)),
None => return Err(ApiError::BadRequest(HOURS_TOO_LARGE)),
};

let val = doc! {
Expand Down Expand Up @@ -120,7 +120,6 @@ pub async fn get_zerotier_members(db: &Client) -> Result<Vec<ZerotierMember>, Ap
// Use aggregation pipeline to extract only relevant fields from database
let pipeline = vec![
doc! {
// get entries within last <cutoff> days
"$match": {
"config.authorized": true
}
Expand Down Expand Up @@ -154,19 +153,19 @@ pub async fn get_zerotier_members(db: &Client) -> Result<Vec<ZerotierMember>, Ap
}

// Return the most recent record for hosts stored in `holoport_status` collection
// Ignores records older than <cutoff> days
// Ignores records older than <cutoff> hours
pub async fn get_hosts_stats(db: &Client, cutoff: u64) -> Result<Vec<HostStats>, ApiError> {
let cutoff_ms = match get_cutoff_timestamp(cutoff) {
Some(x) => x,
None => return Err(ApiError::BadRequest(DAYS_TOO_LARGE)),
None => return Err(ApiError::BadRequest(HOURS_TOO_LARGE)),
};

let hp_status: Collection<HostStats> =
db.database("host_statistics").collection("holoport_status");

let pipeline = vec![
doc! {
// get entries within last <cutoff> days
// get entries within last <cutoff> hours
"$match": {
"timestamp": {"$gte": cutoff_ms}
}
Expand Down Expand Up @@ -229,13 +228,13 @@ pub async fn get_hosts_stats(db: &Client, cutoff: u64) -> Result<Vec<HostStats>,
}

// Helper function to get cutoff timestamp for filter
// We use u64 for days because otherwise we have to recast as u64 in the function, and 4 bytes isn't a big deal here
// Returns None if days is too large and causes negative timestamp (propagates .checked_sub() which does the same)
fn get_cutoff_timestamp(days: u64) -> Option<i64> {
// We use u64 for hours because otherwise we have to recast as u64 in the function, and 4 bytes isn't a big deal here
// Returns None if hours is too large and causes negative timestamp (propagates .checked_sub() which does the same)
fn get_cutoff_timestamp(hours: u64) -> Option<i64> {
let current_timestamp = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("SystemTime should be after unix epoch");
let valid_duration = Duration::from_secs(60 * 60 * 24 * days);
let valid_duration = Duration::from_secs(60 * 60 * hours);

let cutoff_timestamp = current_timestamp.checked_sub(valid_duration)?;
use std::convert::TryInto;
Expand Down
8 changes: 4 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ async fn uptime(name: String, pool: &State<db::AppDbPool>) -> Result<Option<Json
Ok(None)
}

#[get("/list-available?<days>")]
#[get("/list-available?<hours>")]
async fn list_available(
days: u64,
hours: u64,
pool: &State<db::AppDbPool>,
) -> Result<Json<Vec<HostInfo>>, ApiError> {
// TODO: return BAD_REQUEST if days not passed
let hosts = db::get_hosts_stats(&pool.mongo, days).await?;
// TODO: return BAD_REQUEST if hours not passed
let hosts = db::get_hosts_stats(&pool.mongo, hours).await?;
let members = db::get_zerotier_members(&pool.mongo).await?;

Ok(Json(list_available_hosts(hosts, members).await?))
Expand Down

0 comments on commit 6a0805d

Please sign in to comment.