Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Database
DATABASE_URL=postgresql://postgres:rindexer@localhost:5440/postgres
POSTGRES_PASSWORD=rindexer
DATABASE_URL=rindexer.db
API_PORT=3000

# Indexer & API
Expand Down
31 changes: 3 additions & 28 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ edition = "2024"

[dependencies]
axum = "0.7"
tokio = { version = "1.48", features = ["full"] }
sqlx = { version = "0.8.6", features = ["runtime-tokio", "tls-rustls", "postgres", "chrono", "json"] }
tokio = { version = "1.48", default-features = false }
sqlx = { version = "0.8.6", features = ["runtime-tokio", "json", "sqlite"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tower-http = { version = "0.5", features = ["cors"] }
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ RUN cargo build --release

FROM debian:bullseye-slim

RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y ca-certificates libsqlite3-0 && rm -rf /var/lib/apt/lists/*

COPY --from=builder /usr/src/app/target/release/subindexer /usr/local/bin/subindexer

Expand Down
38 changes: 9 additions & 29 deletions docker-compose.prod.yaml
Original file line number Diff line number Diff line change
@@ -1,44 +1,24 @@
volumes:
postgres_data:
sqlite_data:
driver: local

services:
postgresql:
image: postgres:18
shm_size: 1g
restart: always
volumes:
- postgres_data:/var/lib/postgresql
ports:
- 5440:5432
env_file:
- ./.env
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
start_period: 10s
indexer:
image: ghcr.io/joshstevens19/rindexer
depends_on:
postgresql:
condition: service_healthy
image: ghcr.io/bh2smith/rindexer:sha-c0ea448eaabbff6a331c6538fae3016702e53817
volumes:
- .:/app/project_path
- /var/run/docker.sock:/var/run/docker.sock
working_dir: /app/project_path
- sqlite_data:/app/data
working_dir: /app
entrypoint: ["/app/rindexer"]
command: [ "start", "indexer"]
environment:
DATABASE_URL: postgres://postgres:rindexer@postgresql:5432/postgres
DATABASE_URL: /app/data/rindexer.db

api:
image: ghcr.io/deluxtreme/subindexer:latest
depends_on:
postgresql:
condition: service_healthy
volumes:
- sqlite_data:/app/data
environment:
DATABASE_URL: postgres://postgres:rindexer@postgresql:5432/postgres
DATABASE_URL: /app/data/rindexer.db
REDEEMER_PK: ${REDEEMER_PK}
API_PORT: ${API_PORT:-3000}
REDEEM_INTERVAL: ${REDEEM_INTERVAL:-3600}
Expand Down
34 changes: 6 additions & 28 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,34 +1,12 @@
volumes:
postgres_data:
driver: local

services:
postgresql:
image: postgres:18
shm_size: 1g
restart: always
volumes:
- postgres_data:/var/lib/postgresql
ports:
- 5440:5432
environment:
POSTGRES_PASSWORD: rindexer
env_file:
- ./.env
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
start_period: 10s
indexer:
image: ghcr.io/joshstevens19/rindexer
depends_on:
postgresql:
condition: service_healthy
build:
context: .
dockerfile: Dockerfile.indexer
volumes:
- .:/app/project_path
working_dir: /app/project_path
command: [ "start", "indexer"]
entrypoint: ["/app/rindexer"]
command: ["start", "indexer"]
environment:
DATABASE_URL: postgres://postgres:rindexer@postgresql:5432/postgres
DATABASE_URL: rindexer.db
2 changes: 1 addition & 1 deletion rindexer.yaml.template
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ networks:
chain_id: 100
rpc: $GNOSIS_RPC_URL
storage:
postgres:
sqlite:
enabled: true
native_transfers:
enabled: false
Expand Down
17 changes: 5 additions & 12 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,16 @@ use axum::{
extract::{Query, State},
};
use serde::Deserialize;
use sqlx::PgPool;
use sqlx::SqlitePool;

pub async fn get_redeemable(
State(pool): State<PgPool>,
State(pool): State<SqlitePool>,
) -> Json<Vec<models::RedeemableSubscription>> {
let current_timestamp = chrono::Utc::now().timestamp() as i32;
match db::get_redeemable_subscriptions(&pool, current_timestamp).await {
Ok(subscriptions) => Json(subscriptions),
Err(sqlx::Error::Database(db_err))
if db_err.code() == Some(std::borrow::Cow::Borrowed("42P01")) =>
{
// Table doesn't exist yet, return empty list
tracing::warn!("Database tables don't exist yet, returning empty list");
Json(Vec::new())
}
Err(e) => {
// Log other database errors but don't panic
// Log database errors but don't panic (tables might not exist yet)
tracing::error!("Database error: {}", e);
Json(Vec::new())
}
Expand All @@ -35,7 +28,7 @@ pub struct SubscriptionsQuery {
}

pub async fn get_subscriptions(
State(pool): State<PgPool>,
State(pool): State<SqlitePool>,
Query(query): Query<SubscriptionsQuery>,
) -> Result<Json<Vec<models::Subscription>>, (axum::http::StatusCode, Json<serde_json::Value>)> {
match db::get_user_subscriptions(&pool, query.subscriber, query.recipient).await {
Expand All @@ -51,7 +44,7 @@ pub async fn get_subscriptions(
}
}

pub async fn health_check(State(pool): State<PgPool>) -> Json<serde_json::Value> {
pub async fn health_check(State(pool): State<SqlitePool>) -> Json<serde_json::Value> {
// Test database connectivity
let db_healthy = (sqlx::query("SELECT 1").execute(&pool).await).is_ok();
let blocks_behind = db::check_liveness(&pool).await.unwrap_or(u64::MAX);
Expand Down
9 changes: 5 additions & 4 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::{env, str::FromStr};

use alloy::signers::local::PrivateKeySigner;
use sqlx::{PgPool, postgres::PgPoolOptions};
use sqlx::{SqlitePool, sqlite::SqlitePoolOptions};

// One hour on (gnosis chain).
pub const STALE_BLOCK_THRESHOLD: u64 = 12 * 60;

pub struct Config {
pub pool: PgPool,
pub pool: SqlitePool,
pub redeemer: Option<PrivateKeySigner>,
// Optional overrides:
pub api_port: u16,
Expand All @@ -18,11 +18,12 @@ pub struct Config {
impl Config {
pub async fn from_env() -> Self {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let pool = PgPoolOptions::new()
tracing::info!("Connecting to SQLite database at {}", database_url);
let pool = SqlitePoolOptions::new()
.max_connections(2)
.connect(&database_url)
.await
.expect("Failed to connect to Postgres");
.expect("Failed to connect to SQLite");
let redeemer_pk = env::var("REDEEMER_PK").ok();
Self {
pool,
Expand Down
18 changes: 10 additions & 8 deletions src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use alloy::{
primitives::Address,
providers::{Provider, ProviderBuilder},
};
use anyhow::Result;
use sqlx::PgPool;
use anyhow::{Context, Result};
use sqlx::SqlitePool;

const REDEEMABLE_QUERY: &str = include_str!("queries/redeemable.sql");

pub async fn get_redeemable_subscriptions(
pool: &PgPool,
pool: &SqlitePool,
current_timestamp: i32,
) -> Result<Vec<RedeemableSubscription>, sqlx::Error> {
sqlx::query_as::<_, RedeemableSubscription>(REDEEMABLE_QUERY)
Expand All @@ -18,18 +18,20 @@ pub async fn get_redeemable_subscriptions(
.await
}

async fn get_last_synced_block(pool: &PgPool) -> Result<u64, sqlx::Error> {
async fn get_last_synced_block(pool: &SqlitePool) -> Result<u64, sqlx::Error> {
sqlx::query_scalar::<_, i64>(
"SELECT block::bigint FROM rindexer_internal.latest_block WHERE network = 'gnosis'",
"SELECT block FROM rindexer_internal_latest_block WHERE network = 'gnosis'",
)
.fetch_one(pool)
.await
.map(|result| result as u64)
}

// Returns number of blocks behind latest
pub async fn check_liveness(pool: &PgPool) -> Result<u64> {
let last_synced_block = get_last_synced_block(pool).await?;
pub async fn check_liveness(pool: &SqlitePool) -> Result<u64> {
let last_synced_block = get_last_synced_block(pool)
.await
.context("Failed to get last synced block")?;

// Use a different RPC as indexer (because node may not be synced.)
let provider = ProviderBuilder::new().connect_http("https://rpc.gnosischain.com/".parse()?);
Expand All @@ -40,7 +42,7 @@ pub async fn check_liveness(pool: &PgPool) -> Result<u64> {
const USER_SUBSCRIPTIONS_QUERY: &str = include_str!("queries/user_subscriptions.sql");

pub async fn get_user_subscriptions(
pool: &PgPool,
pool: &SqlitePool,
subscriber: Option<Address>,
recipient: Option<Address>,
) -> Result<Vec<Subscription>, sqlx::Error> {
Expand Down
Loading