Skip to content

Instantly share code, notes, and snippets.

@makvoid
Created August 25, 2022 16:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save makvoid/a76bcfcf516ac4f336e273f2dc7faa06 to your computer and use it in GitHub Desktop.
Save makvoid/a76bcfcf516ac4f336e273f2dc7faa06 to your computer and use it in GitHub Desktop.
"How to use Algolia as a game engine debugging tool in Rust" Example #2
use serde::{Deserialize, Serialize, Serializer};
use urlencoding;
// The credentials data
const ALGOLIA_AGENT: &str = "Algolia DataSender for Rust Dev (0.0.1)";
// The reqwest client type used by the library
type ClientType = reqwest::blocking::Client;
pub struct AlgoliaSender {
app_id: String,
api_key: String,
index_name: String,
data_buffer: Vec<String>,
client: ClientType,
}
impl AlgoliaSender {
pub fn new(app_id: &str, api_key: &str, index_name: &str) -> Self {
AlgoliaSender {
app_id: String::from(app_id),
api_key: String::from(api_key),
index_name: String::from(index_name),
data_buffer: vec![],
client: ClientType::new(),
}
}
pub fn add_item<T>(&mut self, v: &T)
where
T: Serialize,
{
match serde_json::to_string(v) {
Ok(serialized) => {
self.data_buffer.push(serialized);
}
Err(_) => {}
}
}
// Sends items to the ingestion endpoint in a batch job
pub fn send_items(&mut self) {
let index_name = self.index_name.clone();
self.send_items_to_index(index_name.as_str());
}
// Sends items to the ingestion endpoint in a batch job
pub fn send_items_to_index(&mut self, index_name: &str) {
// convert a pre-serialized JSON object into a request object for a batch request
fn build_batch_request_entry(data: &String) -> String {
format!("{{\"action\":\"updateObject\",\"body\":{}}}", data)
}
// wrap the individual requests into a batch
fn wrap_batch_request_entry(rows: &Vec<String>) -> String {
format!("{{\"requests\":[{}]}}", rows.join(","))
}
// wrap the data
let data = wrap_batch_request_entry(
&self
.data_buffer
.iter()
.map(build_batch_request_entry)
.collect(),
);
// get the URI for the index
let uri = self.uri_for_index(index_name);
let uri_with_client = format!("{}?x-algolia-agent={}", uri, ALGOLIA_AGENT);
let res = self
.client
.post(uri_with_client)
.header("x-algolia-api-key", self.api_key.as_str())
.header("x-algolia-application-id", self.app_id.as_str())
.body(data)
.send();
match res {
Err(_) => {}
Ok(resp) => {
let status = resp.status();
let body = resp.text().unwrap_or_default();
if status != 200 {
// log the problem for now
println!("ERROR while sending to Algolia: {}\n {}", status, body);
}
}
}
// TODO: this clean is tricky to place, as we want to keep unsent data, but it may accumulate to very large amounts
self.data_buffer.clear();
}
// returns a full URI for an index name and the current app
fn uri_for_index(&self, index_name: &str) -> String {
// build the URI for the batch
let host = format!("{}.algolia.net", self.app_id.to_lowercase());
let path = format!("/1/indexes/{}/batch", urlencoding::encode(index_name));
format!("https://{}{}", host, path)
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Serialize, Debug)]
struct Float3 {
#[serde(rename = "objectID")]
object_id: String,
x: f32,
y: f32,
z: f32,
}
// The credentials data
const APP_ID: &str = "";
const INDEX_NAME: &str = "";
const API_KEY: &str = "";
const ALGOLIA_AGENT: &str = "Algolia DataSender for Rust Dev (0.0.1)";
let mut sender = AlgoliaSender::new(APP_ID, API_KEY, INDEX_NAME);
sender.add_item(&Float3 {
object_id: String::from("point3"),
x: 0.1,
y: 0.2,
z: 0.3,
});
sender.add_item(&Float3 {
object_id: String::from("point4"),
x: 1.1,
y: 1.2,
z: 1.3,
});
sender.send_items();
return Ok(());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment