wingfoil 8.0.0

graph based stream processing framework
Documentation
# PostgreSQL Adapter Example

Round-trips data through PostgreSQL: generates trades, writes them with
`postgres_write`, reads them back with the time-sliced `postgres_read`, and asserts
the two streams tie out. Demonstrates the on-graph time model (`(NanoTime, T)` tuples)
and the shared time-slicing logic used for historical replay.

## Setup

```sh
docker run --rm -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:16-alpine
```

## Run

```sh
cargo run --example postgres --features postgres
```

## Code

```rust
use anyhow::Result;
use ordered_float::OrderedFloat;
use std::rc::Rc;
use wingfoil::adapters::postgres::*;
use wingfoil::*;

type Price = OrderedFloat<f64>;

#[derive(Debug, Clone, Default, PartialEq, Eq)]
struct Trade {
    sym: String,
    price: Price,
    qty: i64,
}

impl PostgresDeserialize for Trade {
    fn from_row(row: &Row) -> Result<(NanoTime, Self)> {
        Ok((
            row.get_nanotime(0)?, // col 0: time
            Trade {
                sym: row.try_get(1)?,
                price: OrderedFloat(row.try_get(2)?),
                qty: row.try_get(3)?,
            },
        ))
    }
}

impl PostgresSerialize for Trade {
    fn to_params(&self) -> Vec<Box<dyn ToSql + Sync + Send>> {
        vec![
            Box::new(self.sym.clone()),
            Box::new(self.price.into_inner()),
            Box::new(self.qty),
        ]
    }
}

fn main() -> Result<()> {
    let conn = PostgresConnection::new(
        "host=localhost port=5432 user=postgres password=postgres dbname=postgres",
    );
    let run_mode = RunMode::HistoricalFrom(NanoTime::from_kdb_timestamp(0));
    let run_for = RunFor::Duration(std::time::Duration::from_secs(11));

    // ... create the table, then:
    generate(10)
        .postgres_write(conn.clone(), "example_trades")
        .run(run_mode, run_for)?;

    let read = postgres_read::<Trade>(
        conn,
        std::time::Duration::from_secs(86400),
        move |(t0, t1), _date, _iter| {
            format!(
                "SELECT time, sym, price, qty FROM example_trades \
                 WHERE time >= '{}' AND time < '{}' ORDER BY time",
                postgres_timestamp(t0),
                postgres_timestamp(t1),
            )
        },
    );
    // ... run and tie out
    Ok(())
}
```

See [`main.rs`](./main.rs) for the full listing.

## Output

```
✓ 10 written, read and validated
```