clippy and cargo fmt
This commit is contained in:
parent
bc5f0b4d49
commit
aaf91271c5
10 changed files with 120 additions and 81 deletions
|
@ -68,7 +68,9 @@ impl<R: Resolver> State<R> {
|
|||
.with_database(db)
|
||||
.create(&secret)
|
||||
.await?;
|
||||
room.get_state().set_config(&actor, &secret, room.get_root().id()).await;
|
||||
room.get_state()
|
||||
.set_config(&actor, &secret, room.get_root().id())
|
||||
.await;
|
||||
room.resolve_state().await;
|
||||
Ok(State { room, secret })
|
||||
}
|
||||
|
@ -187,7 +189,7 @@ async fn sync_http(
|
|||
.map(|ev| ev.id())
|
||||
.cloned()
|
||||
.collect();
|
||||
let mut missing_ids: Vec<EventId> = req.heads.iter().cloned().collect();
|
||||
let mut missing_ids: Vec<EventId> = req.heads.to_vec();
|
||||
|
||||
// this would be batched, to find multiple missing events at once
|
||||
while let Some(next) = missing_ids.pop() {
|
||||
|
@ -222,7 +224,8 @@ async fn serve(state: ServerState) -> Result<()> {
|
|||
|
||||
async fn sync_state(state: &mut State<ForumResolver>, remote: &str) -> Result<()> {
|
||||
let http = reqwest::Client::new();
|
||||
let res: SyncResponse = http.post(remote)
|
||||
let res: SyncResponse = http
|
||||
.post(remote)
|
||||
.json(&SyncRequest {
|
||||
root_id: state.room.get_root().id().to_owned(),
|
||||
heads: state.room.get_heads().await,
|
||||
|
|
|
@ -6,8 +6,11 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use dag_resolve::{
|
||||
actor::ActorId,
|
||||
event::{EventContent, Event, EventId},
|
||||
proto::{data::Text, table::{Database, Table as _}},
|
||||
event::{Event, EventContent, EventId},
|
||||
proto::{
|
||||
data::Text,
|
||||
table::{Database, Table as _},
|
||||
},
|
||||
resolver::{Command, Resolver, Verification},
|
||||
};
|
||||
|
||||
|
@ -104,7 +107,7 @@ fn can_send_event(
|
|||
}
|
||||
|
||||
impl ForumMemberAcl {
|
||||
fn to_str(&self) -> &str {
|
||||
fn as_str(&self) -> &str {
|
||||
match self {
|
||||
ForumMemberAcl::Mute => "mute",
|
||||
ForumMemberAcl::None => "none",
|
||||
|
@ -125,7 +128,7 @@ impl ForumMemberAcl {
|
|||
}
|
||||
|
||||
impl ForumRoomAcl {
|
||||
fn to_str(&self) -> &str {
|
||||
fn as_str(&self) -> &str {
|
||||
match self {
|
||||
ForumRoomAcl::Public => "public",
|
||||
ForumRoomAcl::Voice => "voice",
|
||||
|
@ -147,11 +150,17 @@ impl ForumRoomAcl {
|
|||
impl Resolver for ForumResolver {
|
||||
type EventType = ForumEventContent;
|
||||
|
||||
async fn resolve<S: Database>(&self, _state: &S, event: &Event<Self::EventType>) -> Vec<Command> {
|
||||
async fn resolve<S: Database>(
|
||||
&self,
|
||||
_state: &S,
|
||||
event: &Event<Self::EventType>,
|
||||
) -> Vec<Command> {
|
||||
let row = match event.content() {
|
||||
EventContent::Create(_) => {
|
||||
Command::put("members", event.author().to_string().as_bytes(), ForumMemberAcl::Operator.to_str().as_bytes())
|
||||
}
|
||||
EventContent::Create(_) => Command::put(
|
||||
"members",
|
||||
event.author().to_string().as_bytes(),
|
||||
ForumMemberAcl::Operator.as_str().as_bytes(),
|
||||
),
|
||||
EventContent::Custom(ForumEventContent::Post { .. }) => {
|
||||
Command::put("posts", event.id().to_string().as_bytes(), b"")
|
||||
}
|
||||
|
@ -171,12 +180,14 @@ impl Resolver for ForumResolver {
|
|||
return vec![
|
||||
Command::put("meta", b"name", serde_json::to_vec(name).unwrap()),
|
||||
Command::put("meta", b"topic", serde_json::to_vec(topic).unwrap()),
|
||||
Command::put("meta", b"acl", acl.to_str().as_bytes()),
|
||||
Command::put("meta", b"acl", acl.as_str().as_bytes()),
|
||||
]
|
||||
}
|
||||
EventContent::Custom(ForumEventContent::Member { id, acl }) => {
|
||||
Command::put("members", id.to_string().as_bytes(), acl.to_str().as_bytes())
|
||||
}
|
||||
EventContent::Custom(ForumEventContent::Member { id, acl }) => Command::put(
|
||||
"members",
|
||||
id.to_string().as_bytes(),
|
||||
acl.as_str().as_bytes(),
|
||||
),
|
||||
};
|
||||
vec![row]
|
||||
}
|
||||
|
@ -192,7 +203,7 @@ impl Resolver for ForumResolver {
|
|||
async fn verify<D: Database>(&self, state: &D, event: &Event<Self::EventType>) -> Verification {
|
||||
let member_entry = state
|
||||
.table("members")
|
||||
.get(&event.author().to_string().as_bytes())
|
||||
.get(event.author().to_string().as_bytes())
|
||||
.await
|
||||
.and_then(|b| String::from_utf8(b).ok())
|
||||
.map(|s| ForumMemberAcl::from_str(&s))
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use dag_resolve::{
|
||||
event::{EventContent, Event},
|
||||
event::{Event, EventContent},
|
||||
proto::table::{Database, Table as _},
|
||||
resolver::{Command, Resolver, Verification},
|
||||
};
|
||||
|
@ -29,7 +29,11 @@ impl KVResolver {
|
|||
impl Resolver for KVResolver {
|
||||
type EventType = KVEventContent;
|
||||
|
||||
async fn resolve<D: Database>(&self, _state: &D, event: &Event<KVEventContent>) -> Vec<Command> {
|
||||
async fn resolve<D: Database>(
|
||||
&self,
|
||||
_state: &D,
|
||||
event: &Event<KVEventContent>,
|
||||
) -> Vec<Command> {
|
||||
match &event.content() {
|
||||
EventContent::Create(_) => {
|
||||
vec![Command::Put {
|
||||
|
@ -53,7 +57,8 @@ impl Resolver for KVResolver {
|
|||
}
|
||||
|
||||
async fn verify<D: Database>(&self, state: &D, event: &Event<Self::EventType>) -> Verification {
|
||||
if state.table("meta").get(b"owner").await.unwrap() == event.author().to_string().as_bytes() {
|
||||
if state.table("meta").get(b"owner").await.unwrap() == event.author().to_string().as_bytes()
|
||||
{
|
||||
Verification::Valid
|
||||
} else {
|
||||
Verification::Invalid
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! Contains premade resolvers
|
||||
|
||||
pub mod kv;
|
||||
pub mod forum;
|
||||
pub mod kv;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
//! Store state in a sqlite database
|
||||
|
||||
use dag_resolve::{
|
||||
actor::{ActorId, ActorSecret}, event::EventId, proto::table::{self, Database as _}, room::{TABLE_EVENTS, TABLE_HEADS}
|
||||
actor::{ActorId, ActorSecret},
|
||||
event::EventId,
|
||||
proto::table::{self, Database as _},
|
||||
room::{TABLE_EVENTS, TABLE_HEADS},
|
||||
};
|
||||
use sqlx::{query, sqlite::SqliteConnectOptions, SqlitePool};
|
||||
use thiserror::Error;
|
||||
|
@ -57,25 +60,33 @@ impl Database {
|
|||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
|
||||
pub async fn get_config(&self) -> (ActorId, ActorSecret, EventId) {
|
||||
let rows = query!("SELECT * FROM config").fetch_all(&self.connection).await.unwrap();
|
||||
let rows = query!("SELECT * FROM config")
|
||||
.fetch_all(&self.connection)
|
||||
.await
|
||||
.unwrap();
|
||||
let mut actor_id = None;
|
||||
let mut secret = None;
|
||||
let mut root_id = None;
|
||||
for row in rows {
|
||||
match row.key.as_deref() {
|
||||
Some("actor_id") => actor_id = row.value.map(|s| s.parse().unwrap()),
|
||||
Some("actor_secret") => secret = row.value.map(|s| serde_json::from_str(&s).unwrap()),
|
||||
Some("actor_secret") => {
|
||||
secret = row.value.map(|s| serde_json::from_str(&s).unwrap())
|
||||
}
|
||||
Some("root_id") => root_id = row.value.map(|s| s.parse().unwrap()),
|
||||
_ => {},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
(actor_id.unwrap(), secret.unwrap(), root_id.unwrap())
|
||||
}
|
||||
|
||||
|
||||
pub async fn data_count(&self) -> u64 {
|
||||
let rows = query!("SELECT count(*) as count FROM data").fetch_one(&self.connection).await.unwrap();
|
||||
let rows = query!("SELECT count(*) as count FROM data")
|
||||
.fetch_one(&self.connection)
|
||||
.await
|
||||
.unwrap();
|
||||
rows.count as u64
|
||||
}
|
||||
}
|
||||
|
@ -100,10 +111,14 @@ impl table::Database for Database {
|
|||
CREATE TABLE IF NOT EXISTS data (tb TEXT, key BLOB, value BLOB NOT NULL, PRIMARY KEY(tb, key));
|
||||
CREATE TABLE IF NOT EXISTS config (key TEXT PRIMARY KEY, value TEXT);
|
||||
").execute(&self.connection).await.unwrap();
|
||||
query!("DELETE FROM data WHERE tb NOT IN (?, ?)", TABLE_EVENTS, TABLE_HEADS)
|
||||
.execute(&self.connection)
|
||||
.await
|
||||
.unwrap();
|
||||
query!(
|
||||
"DELETE FROM data WHERE tb NOT IN (?, ?)",
|
||||
TABLE_EVENTS,
|
||||
TABLE_HEADS
|
||||
)
|
||||
.execute(&self.connection)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn table(&self, name: impl Into<String>) -> Self::Table {
|
||||
|
@ -135,18 +150,17 @@ impl table::Table for Table {
|
|||
|
||||
async fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
let keyvec = key.to_vec();
|
||||
let row =
|
||||
query!(
|
||||
"SELECT value FROM data WHERE tb = ? AND key = ?",
|
||||
self.name,
|
||||
keyvec
|
||||
)
|
||||
.fetch_one(&self.connection)
|
||||
.await;
|
||||
let row = query!(
|
||||
"SELECT value FROM data WHERE tb = ? AND key = ?",
|
||||
self.name,
|
||||
keyvec
|
||||
)
|
||||
.fetch_one(&self.connection)
|
||||
.await;
|
||||
match row {
|
||||
Ok(row) => Some(row.value),
|
||||
Err(sqlx::Error::RowNotFound) => None,
|
||||
Err(err) => Err(err).unwrap(),
|
||||
Err(err) => panic!("{:?}", err),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,31 +177,25 @@ impl table::Table for Table {
|
|||
}
|
||||
|
||||
async fn delete(&self, key: &[u8]) {
|
||||
query!(
|
||||
"DELETE FROM data WHERE tb = ? AND key = ?",
|
||||
self.name,
|
||||
key,
|
||||
)
|
||||
.execute(&self.connection)
|
||||
.await
|
||||
.unwrap();
|
||||
query!("DELETE FROM data WHERE tb = ? AND key = ?", self.name, key,)
|
||||
.execute(&self.connection)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl table::Query for Query {
|
||||
async fn get_single(self) -> Option<Vec<u8>> {
|
||||
match self.selector {
|
||||
table::Selector::Exact(e) => {
|
||||
query!(
|
||||
"SELECT value FROM data WHERE tb = ? AND key = ?",
|
||||
self.table.name,
|
||||
e
|
||||
)
|
||||
.fetch_optional(&self.table.connection)
|
||||
.await
|
||||
.unwrap()
|
||||
.map(|r| r.value)
|
||||
},
|
||||
table::Selector::Exact(e) => query!(
|
||||
"SELECT value FROM data WHERE tb = ? AND key = ?",
|
||||
self.table.name,
|
||||
e
|
||||
)
|
||||
.fetch_optional(&self.table.connection)
|
||||
.await
|
||||
.unwrap()
|
||||
.map(|r| r.value),
|
||||
table::Selector::Prefix(p) => {
|
||||
let pvec = p.to_vec();
|
||||
let plen = p.len() as i64;
|
||||
|
@ -235,4 +243,3 @@ impl table::Query for Query {
|
|||
self.get_all().await.len() as u64
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,10 +82,9 @@ pub enum EventContent<T> {
|
|||
|
||||
// /// A tombstone marking the end of a room and a potential replacement.
|
||||
// Tombstone,
|
||||
|
||||
|
||||
// /// Aliases are human readable unique identifiers, this event is the "reverse record"
|
||||
// Alias,
|
||||
|
||||
/// Custom data
|
||||
Custom(T),
|
||||
}
|
||||
|
@ -150,7 +149,10 @@ impl<T: Debug + Serialize + Clone> Event<T> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn verify_room<R: Resolver<EventType = T>, D: Database>(&self, room: &Room<R, D>) -> Result<()> {
|
||||
pub fn verify_room<R: Resolver<EventType = T>, D: Database>(
|
||||
&self,
|
||||
room: &Room<R, D>,
|
||||
) -> Result<()> {
|
||||
self.verify()?;
|
||||
|
||||
let room_config = match &room.get_root().content {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
pub mod actor;
|
||||
pub mod data;
|
||||
pub mod event;
|
||||
pub mod resolver;
|
||||
pub mod room;
|
||||
pub mod data;
|
||||
pub mod table;
|
||||
|
|
|
@ -10,14 +10,22 @@ pub trait Resolver {
|
|||
type EventType: Clone + Debug + Serialize + for<'a> Deserialize<'a>;
|
||||
|
||||
/// Given a set of ordered events, resolve the final state
|
||||
fn resolve<D: Database>(&self, state: &D, event: &Event<Self::EventType>) -> impl Future<Output = Vec<Command>>;
|
||||
fn resolve<D: Database>(
|
||||
&self,
|
||||
state: &D,
|
||||
event: &Event<Self::EventType>,
|
||||
) -> impl Future<Output = Vec<Command>>;
|
||||
|
||||
/// Given two events, decide which one comes first
|
||||
/// if Ordering::Equal is returned, the timestamp then event id is used
|
||||
fn tiebreak(&self, a: &Event<Self::EventType>, b: &Event<Self::EventType>) -> Ordering;
|
||||
|
||||
/// Verify if an event can be sent or not
|
||||
fn verify<D: Database>(&self, state: &D, event: &Event<Self::EventType>) -> impl Future<Output = Verification>;
|
||||
fn verify<D: Database>(
|
||||
&self,
|
||||
state: &D,
|
||||
event: &Event<Self::EventType>,
|
||||
) -> impl Future<Output = Verification>;
|
||||
|
||||
/// TEMP: Get the name/id of this resolver
|
||||
fn name(&self) -> &str;
|
||||
|
|
|
@ -52,10 +52,7 @@ impl<R: Resolver, D: Database> Room<R, D> {
|
|||
.table(TABLE_EVENTS)
|
||||
.put(id_bytes, &serde_json::to_vec(&base_event).unwrap())
|
||||
.await;
|
||||
database
|
||||
.table(TABLE_HEADS)
|
||||
.put(id_bytes, &[])
|
||||
.await;
|
||||
database.table(TABLE_HEADS).put(id_bytes, &[]).await;
|
||||
Ok(Self {
|
||||
root: base_event,
|
||||
resolver,
|
||||
|
@ -137,11 +134,17 @@ impl<R: Resolver, D: Database> Room<R, D> {
|
|||
.table(TABLE_EVENTS)
|
||||
.put(id_bytes, &serde_json::to_vec(&event).unwrap())
|
||||
.await;
|
||||
|
||||
|
||||
for head in dbg!(event.references()) {
|
||||
self.database.table(TABLE_HEADS).delete(&head.to_string().into_bytes()).await;
|
||||
self.database
|
||||
.table(TABLE_HEADS)
|
||||
.delete(&head.to_string().into_bytes())
|
||||
.await;
|
||||
}
|
||||
self.database.table(TABLE_HEADS).put(&event.id().to_string().into_bytes(), &[]).await;
|
||||
self.database
|
||||
.table(TABLE_HEADS)
|
||||
.put(&event.id().to_string().into_bytes(), &[])
|
||||
.await;
|
||||
Ok(event)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,20 +4,20 @@ type Bytes = Vec<u8>;
|
|||
|
||||
pub trait Database {
|
||||
type Table: Table;
|
||||
|
||||
|
||||
fn table(&self, name: impl Into<String>) -> Self::Table;
|
||||
fn reset(&self) -> impl Future<Output = ()>;
|
||||
}
|
||||
|
||||
pub trait Table {
|
||||
type Query: Query;
|
||||
|
||||
|
||||
fn query(&self, selector: Selector) -> Self::Query;
|
||||
fn query_reverse(&self, selector: Selector) -> Self::Query;
|
||||
|
||||
|
||||
#[must_use("future must be polled")]
|
||||
fn get(&self, key: &[u8]) -> impl Future<Output = Option<Bytes>>;
|
||||
|
||||
fn get(&self, key: &[u8]) -> impl Future<Output = Option<Bytes>>;
|
||||
|
||||
#[must_use("future must be polled")]
|
||||
fn put(&self, key: &[u8], value: &[u8]) -> impl Future<Output = ()>;
|
||||
|
||||
|
@ -37,8 +37,8 @@ pub trait Query {
|
|||
fn count(self) -> impl Future<Output = u64>;
|
||||
}
|
||||
|
||||
impl Into<Selector> for Vec<u8> {
|
||||
fn into(self) -> Selector {
|
||||
Selector::Exact(self)
|
||||
impl From<Vec<u8>> for Selector {
|
||||
fn from(value: Vec<u8>) -> Self {
|
||||
Selector::Exact(value)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue