Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement fuel_indexer_graphql_dyn::store::Store for dynamic schema resolution #1310

Closed
AlicanC opened this issue Aug 29, 2023 · 0 comments
Closed

Comments

@AlicanC
Copy link
Contributor

AlicanC commented Aug 29, 2023

With the introduction of #1309 it is now possible to start implementing the storage layer for dynamic schema resolution.

The three parts needed can be described as:

/// A `store::Store` implementation.
#[async_trait]
impl Store for MyStore {
    fn r#type(&self) -> &StoreType { ... }
    //
    async fn obj_get(&self, id: &Id) -> R<O<Obj>> { ... }
    async fn obj_get_many(&self, ids: &[Id]) -> R<Vec<O<Obj>>> { ... }
    async fn assoc_get(&self, key: &Key, ...) -> R<Vec<O<Assoc>>> { ... }
    async fn assoc_count(&self, key: &Key, ...) -> R<u64> { ... }
    async fn assoc_range(&self, key: &Key, ...) -> R<Vec<Assoc>> { ... }
    async fn assoc_time_range(&self, key: &Key, ...) -> R<Vec<Assoc>> { ... }
}

/// A `store::StoreType` constructor.
fn new_store_type(config: &MyConfig) -> StoreType {
    let mut store_type = StoreTypeBuilder::default();
    ...
    store_type.finish()
}

/// A `schema::DynSchemaType` constructor.
fn new_schema_type(config: &MyConfig, store_type: &StoreType) -> DynSchemaType {
    let mut schema_type = DynSchemaTypeBuilder::new(store_type);
    ...
    schema_type.finish()
}

The following can be used as an example for the store::Store implementation:

use sqlx::prelude::*;
use fuel_indexer_graphql_dyn::store::*;
use sqlx::{pool::PoolConnection, Postgres};
use std::sync::Arc;
use tokio::sync::Mutex;

pub struct SqlxStore {
    r#type: StoreType,
    conn: Arc<Mutex<PoolConnection<Postgres>>>,
}

impl SqlxStore {
    pub fn new(r#type: StoreType, conn: Arc<Mutex<PoolConnection<Postgres>>>) -> Self {
        Self { r#type, conn }
    }
}

#[async_trait]
impl Store for SqlxStore {
    fn r#type(&self) -> &StoreType {
        &self.r#type
    }
    async fn obj_get(&self, id: &ObjId) -> StoreResult<Option<Obj>> {
        let mut conn = self.conn.lock().await;
        let conn = conn.acquire().await.unwrap();
        let (type_id, local_id) = id.split_once(':').unwrap();
        let table_id = format!("fuellabs_explorer.{}", type_id);
        let local_id: i64 = local_id.parse().unwrap();

        let row: (serde_json::Value,) = sqlx::query_as(&format!(
            r#"
                SELECT (row_to_json(obj)::jsonb)
                FROM (
                    SELECT * FROM {}
                    WHERE id = $1
                ) AS obj
            "#,
            table_id
        ))
        .bind(local_id)
        .fetch_one(conn)
        .await
        .unwrap();
        Ok(Some(Obj::new(type_id.to_string(), Data::Json(row.0))))
    }
    async fn obj_get_many(&self, ids: &[ObjId]) -> StoreResult<Vec<Option<Obj>>> {
        todo!()
    }
    async fn assoc_get(
        &self,
        key: &AssocKey,
        ids: &[ObjId],
        high: Option<AssocTime>,
        low: Option<AssocTime>,
    ) -> StoreResult<Vec<Option<Assoc>>> {
        todo!()
    }
    async fn assoc_count(&self, key: &AssocKey) -> StoreResult<u64> {
        todo!()
    }
    async fn assoc_range(
        &self,
        key: &AssocKey,
        offset: u64,
        limit: u64,
    ) -> StoreResult<Vec<Assoc>> {
        todo!()
    }
    async fn assoc_time_range(
        &self,
        key: &AssocKey,
        high: AssocTime,
        low: AssocTime,
        limit: u64,
    ) -> StoreResult<Vec<Assoc>> {
        todo!()
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants