Skip to content

Commit b564d31

Browse files
chore: Run backend queries parallely
1 parent 1f9836c commit b564d31

1 file changed

Lines changed: 126 additions & 68 deletions

File tree

backend/src/main.rs

Lines changed: 126 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use pallas::ledger::primitives::{PlutusData, ToCanonicalJson};
88
use reqwest::Client;
99
use rocket::State;
1010
use rocket::fairing::{Fairing, Info, Kind};
11+
use rocket::futures::future::join_all;
1112
use rocket::http::{Header, Method, Status};
1213
use rocket::response::content::RawHtml;
1314
use serde_json::Value;
@@ -154,7 +155,7 @@ fn decode_asset_name(hex_name: &str) -> Result<String, Error> {
154155
})
155156
}
156157

157-
fn distance_from_center(x: i32, y: i32, center: PositionInput) -> i32 {
158+
fn distance_from_center(x: i32, y: i32, center: &PositionInput) -> i32 {
158159
(x - center.x).abs() + (y - center.y).abs()
159160
}
160161

@@ -351,6 +352,103 @@ async fn fetch_utxos_by_address(
351352
.map_err(|e| Error::new(e.to_string()))
352353
}
353354

355+
async fn ships_in_radius(
356+
api: &BlockfrostAPI,
357+
spacetime_address: &str,
358+
spacetime_policy_id: &str,
359+
pellet_policy_id: &str,
360+
radius: i32,
361+
center: &PositionInput,
362+
) -> Result<Vec<PositionalInterface>, Error> {
363+
Ok(
364+
fetch_utxos_by_policy(api, spacetime_address, spacetime_policy_id)
365+
.await?
366+
.into_iter()
367+
.map(|x| {
368+
Ship::try_from((
369+
spacetime_policy_id.to_string(),
370+
pellet_policy_id.to_string(),
371+
x,
372+
))
373+
})
374+
.collect::<Result<Vec<Ship>, Error>>()?
375+
.into_iter()
376+
.filter(|ship| {
377+
let distance = distance_from_center(ship.position.x, ship.position.y, center);
378+
distance < radius
379+
})
380+
.map(|ship| PositionalInterface::Ship(ship.clone()))
381+
.collect::<Vec<PositionalInterface>>(),
382+
)
383+
}
384+
385+
async fn pellets_in_radius(
386+
api: &BlockfrostAPI,
387+
pellet_address: &str,
388+
pellet_policy_id: &str,
389+
radius: i32,
390+
center: &PositionInput,
391+
) -> Result<Vec<PositionalInterface>, Error> {
392+
Ok(
393+
fetch_utxos_by_policy(api, pellet_address, pellet_policy_id)
394+
.await?
395+
.into_iter()
396+
.map(|x| Pellet::try_from((pellet_policy_id.to_string(), x)))
397+
.collect::<Result<Vec<Pellet>, Error>>()?
398+
.into_iter()
399+
.filter(|pellet| {
400+
let distance = distance_from_center(pellet.position.x, pellet.position.y, center);
401+
distance < radius
402+
})
403+
.map(|pellet| PositionalInterface::Pellet(pellet.clone()))
404+
.collect::<Vec<PositionalInterface>>(),
405+
)
406+
}
407+
408+
async fn asteria_in_radius(
409+
api: &BlockfrostAPI,
410+
asteria_address: &str,
411+
spacetime_policy_id: &str,
412+
radius: i32,
413+
center: &PositionInput,
414+
) -> Result<Option<PositionalInterface>, Error> {
415+
for utxo in fetch_utxos_by_address(api, asteria_address).await? {
416+
let datum_json = inline_datum_json(&utxo.inline_datum)?;
417+
let spacetime_policy = datum_bytes(&datum_json, 1)?;
418+
if spacetime_policy != spacetime_policy_id {
419+
continue;
420+
}
421+
let asteria = Asteria::try_from(utxo)?;
422+
423+
let distance = distance_from_center(asteria.position.x, asteria.position.y, center);
424+
if distance >= radius {
425+
continue;
426+
}
427+
428+
return Ok(Some(PositionalInterface::Asteria(asteria)));
429+
}
430+
Ok(None)
431+
}
432+
433+
async fn tokens_in_radius(
434+
api: &BlockfrostAPI,
435+
pellet_address: &str,
436+
token: &TokenInput,
437+
radius: i32,
438+
center: &PositionInput,
439+
) -> Result<Vec<PositionalInterface>, Error> {
440+
Ok(fetch_utxos_by_policy(api, pellet_address, &token.policy_id)
441+
.await?
442+
.into_iter()
443+
.map(|utxo| Token::try_from((token.clone(), utxo)))
444+
.collect::<Result<Vec<Token>, Error>>()?
445+
.into_iter()
446+
.filter(|token| distance_from_center(token.position.x, token.position.y, center) <= radius)
447+
.filter(|token| token.amount > 0)
448+
.map(PositionalInterface::Token)
449+
.collect())
450+
}
451+
354452
struct QueryRoot;
355453

356454
#[derive(Clone)]
@@ -560,75 +658,35 @@ impl QueryRoot {
560658

561659
let mut map_objects = Vec::new();
562660

563-
for utxo in fetch_utxos_by_policy(api, &spacetime_address, &spacetime_policy_id).await? {
564-
let ship =
565-
Ship::try_from((spacetime_policy_id.clone(), pellet_policy_id.clone(), utxo))?;
566-
let distance = distance_from_center(ship.position.x, ship.position.y, center);
567-
if distance >= radius {
568-
continue;
569-
}
570-
571-
map_objects.push(PositionalInterface::Ship(ship));
572-
}
573-
574-
for utxo in fetch_utxos_by_policy(api, &pellet_address, &pellet_policy_id).await? {
575-
let pellet = Pellet::try_from((pellet_policy_id.clone(), utxo))?;
576-
let distance = distance_from_center(pellet.position.x, pellet.position.y, center);
577-
if distance >= radius {
578-
continue;
579-
}
580-
581-
if pellet.spacetime_policy.id.to_string() != spacetime_policy_id {
582-
continue;
583-
}
584-
585-
if pellet.fuel <= 0 {
586-
continue;
587-
}
588-
589-
map_objects.push(PositionalInterface::Pellet(pellet));
590-
}
591-
592-
for utxo in fetch_utxos_by_address(api, &asteria_address).await? {
593-
let datum_json = inline_datum_json(&utxo.inline_datum)?;
594-
let spacetime_policy = datum_bytes(&datum_json, 1)?;
595-
if spacetime_policy != spacetime_policy_id {
596-
continue;
597-
}
598-
let asteria = Asteria::try_from(utxo)?;
599-
600-
let distance = distance_from_center(asteria.position.x, asteria.position.y, center);
601-
if distance >= radius {
602-
continue;
603-
}
604-
605-
map_objects.push(PositionalInterface::Asteria(asteria));
606-
}
607-
608-
if let Some(tokens) = tokens {
609-
for token in tokens {
610-
let token_utxos =
611-
fetch_utxos_by_policy(api, &pellet_address, &token.policy_id).await?;
612-
613-
for utxo in token_utxos {
614-
let map_token = Token::try_from((token.clone(), utxo))?;
615-
let distance =
616-
distance_from_center(map_token.position.x, map_token.position.y, center);
617-
if distance >= radius {
618-
continue;
619-
}
620-
621-
if map_token.spacetime_policy.id.to_string() != spacetime_policy_id {
622-
continue;
623-
}
624-
625-
if map_token.amount <= 0 {
626-
continue;
627-
}
628-
629-
map_objects.push(PositionalInterface::Token(map_token));
661+
let (ships, pellets, asteria, tokens) = tokio::join!(
662+
ships_in_radius(
663+
api,
664+
&spacetime_address,
665+
&spacetime_policy_id,
666+
&pellet_policy_id,
667+
radius,
668+
&center,
669+
),
670+
pellets_in_radius(api, &pellet_address, &pellet_policy_id, radius, &center),
671+
asteria_in_radius(api, &asteria_address, &spacetime_policy_id, radius, &center),
672+
async {
673+
match tokens.as_ref().map(|tokens| {
674+
tokens
675+
.iter()
676+
.map(|token| tokens_in_radius(api, &pellet_address, token, radius, &center))
677+
.collect::<Vec<_>>()
678+
}) {
679+
Some(futs) => join_all(futs).await,
680+
None => Vec::new(),
630681
}
631682
}
683+
);
684+
685+
map_objects.extend(ships?);
686+
map_objects.extend(pellets?);
687+
map_objects.extend(asteria?.into_iter());
688+
for token_objects in tokens {
689+
map_objects.extend(token_objects?);
632690
}
633691

634692
Ok(map_objects)

0 commit comments

Comments
 (0)