use crate::models::dht::{ChainOpPublishRow, OpToPublishRow};
use holo_hash::{AgentPubKey, DhtOpHash};
use holochain_timestamp::Timestamp;
use sqlx::{Executor, Sqlite};
pub(crate) async fn insert_chain_op_publish<'e, E>(
executor: E,
op_hash: &DhtOpHash,
last_publish_time: Option<Timestamp>,
receipts_complete: Option<bool>,
withhold_publish: Option<bool>,
) -> sqlx::Result<()>
where
E: Executor<'e, Database = Sqlite>,
{
sqlx::query(
"INSERT INTO ChainOpPublish (op_hash, last_publish_time, receipts_complete, withhold_publish)
VALUES (?, ?, ?, ?)",
)
.bind(op_hash.get_raw_36())
.bind(last_publish_time.map(|t| t.as_micros()))
.bind(receipts_complete.map(|b| b as i64))
.bind(withhold_publish.map(|b| b as i64))
.execute(executor)
.await?;
Ok(())
}
pub(crate) async fn get_chain_op_publish<'e, E>(
executor: E,
op_hash: DhtOpHash,
) -> sqlx::Result<Option<ChainOpPublishRow>>
where
E: Executor<'e, Database = Sqlite>,
{
sqlx::query_as(
"SELECT op_hash, last_publish_time, receipts_complete, withhold_publish
FROM ChainOpPublish WHERE op_hash = ?",
)
.bind(op_hash.get_raw_36())
.fetch_optional(executor)
.await
}
pub(crate) async fn set_receipts_complete<'e, E>(
executor: E,
op_hash: &DhtOpHash,
) -> sqlx::Result<u64>
where
E: Executor<'e, Database = Sqlite>,
{
let result = sqlx::query("UPDATE ChainOpPublish SET receipts_complete = 1 WHERE op_hash = ?")
.bind(op_hash.get_raw_36())
.execute(executor)
.await?;
Ok(result.rows_affected())
}
pub(crate) async fn set_last_publish_time<'e, E>(
executor: E,
op_hash: &DhtOpHash,
when: Timestamp,
) -> sqlx::Result<u64>
where
E: Executor<'e, Database = Sqlite>,
{
let result = sqlx::query("UPDATE ChainOpPublish SET last_publish_time = ? WHERE op_hash = ?")
.bind(when.as_micros())
.bind(op_hash.get_raw_36())
.execute(executor)
.await?;
Ok(result.rows_affected())
}
pub(crate) async fn clear_withhold_publish<'e, E>(
executor: E,
op_hash: &DhtOpHash,
) -> sqlx::Result<u64>
where
E: Executor<'e, Database = Sqlite>,
{
let result = sqlx::query("UPDATE ChainOpPublish SET withhold_publish = NULL WHERE op_hash = ?")
.bind(op_hash.get_raw_36())
.execute(executor)
.await?;
Ok(result.rows_affected())
}
pub(crate) async fn get_ops_to_publish<'e, E>(
executor: E,
author: &AgentPubKey,
recency_threshold_micros: i64,
) -> sqlx::Result<Vec<OpToPublishRow>>
where
E: Executor<'e, Database = Sqlite>,
{
sqlx::query_as(
"SELECT ChainOp.hash AS dht_hash, ChainOp.basis_hash AS basis_hash, Action.seq AS sort_seq
FROM ChainOp
JOIN Action ON ChainOp.action_hash = Action.hash
LEFT JOIN ChainOpPublish ON ChainOpPublish.op_hash = ChainOp.hash
WHERE Action.author = ?
AND (ChainOp.op_type != 2 OR Action.private_entry = 0)
AND ChainOpPublish.withhold_publish IS NULL
AND (ChainOpPublish.last_publish_time IS NULL
OR ChainOpPublish.last_publish_time <= ?)
AND ChainOpPublish.receipts_complete IS NULL
UNION ALL
SELECT WarrantOp.hash AS dht_hash, Warrant.warrantee AS basis_hash,
9223372036854775807 AS sort_seq
FROM WarrantOp
JOIN Warrant ON WarrantOp.hash = Warrant.hash
LEFT JOIN WarrantPublish ON WarrantPublish.warrant_hash = Warrant.hash
WHERE Warrant.author = ?
AND WarrantPublish.last_publish_time IS NULL
ORDER BY sort_seq, dht_hash",
)
.bind(author.get_raw_36())
.bind(recency_threshold_micros)
.bind(author.get_raw_36())
.fetch_all(executor)
.await
}
pub(crate) async fn num_still_needing_publish<'e, E>(
executor: E,
author: &AgentPubKey,
) -> sqlx::Result<i64>
where
E: Executor<'e, Database = Sqlite>,
{
sqlx::query_scalar(
"SELECT
(SELECT COUNT(*)
FROM ChainOp
JOIN Action ON ChainOp.action_hash = Action.hash
LEFT JOIN ChainOpPublish ON ChainOpPublish.op_hash = ChainOp.hash
WHERE Action.author = ?
AND ChainOpPublish.withhold_publish IS NULL
AND (ChainOp.op_type != 2 OR Action.private_entry = 0)
AND ChainOpPublish.receipts_complete IS NULL)
+ (SELECT COUNT(*)
FROM WarrantOp
JOIN Warrant ON WarrantOp.hash = Warrant.hash
LEFT JOIN WarrantPublish ON WarrantPublish.warrant_hash = Warrant.hash
WHERE Warrant.author = ?
AND WarrantPublish.last_publish_time IS NULL)",
)
.bind(author.get_raw_36())
.bind(author.get_raw_36())
.fetch_one(executor)
.await
}