storage: Start of reprel database

This commit is contained in:
Mike Dilger 2023-11-20 08:07:42 +13:00
parent 5a7e3866b1
commit 351cfd6bc4
2 changed files with 160 additions and 2 deletions

View File

@ -31,6 +31,7 @@ mod person_lists2;
mod person_relays1;
mod relationships1;
mod relays1;
mod reprel1;
mod unindexed_giftwraps1;
use crate::dm_channel::{DmChannel, DmChannelData};
@ -45,8 +46,8 @@ use gossip_relay_picker::Direction;
use heed::types::UnalignedSlice;
use heed::{Database, Env, EnvFlags, EnvOpenOptions, RwTxn};
use nostr_types::{
EncryptedPrivateKey, Event, EventKind, EventReference, Id, MilliSatoshi, PublicKey,
RelayUrl, Tag, Unixtime,
EncryptedPrivateKey, Event, EventAddr, EventKind, EventReference, Id, MilliSatoshi,
PublicKey, RelayUrl, Tag, Unixtime,
};
use paste::paste;
use speedy::{Readable, Writable};
@ -189,6 +190,7 @@ impl Storage {
let _ = self.db_people()?;
let _ = self.db_person_relays()?;
let _ = self.db_relationships()?;
let _ = self.db_reprel()?;
let _ = self.db_relays()?;
let _ = self.db_unindexed_giftwraps()?;
let _ = self.db_person_lists()?;
@ -267,6 +269,11 @@ impl Storage {
self.db_relationships1()
}
#[inline]
pub(crate) fn db_reprel(&self) -> Result<RawDatabase, Error> {
self.db_reprel1()
}
#[inline]
pub(crate) fn db_relays(&self) -> Result<RawDatabase, Error> {
self.db_relays1()
@ -344,6 +351,13 @@ impl Storage {
Ok(self.db_relationships()?.len(&txn)?)
}
/// The number of records in the reprel table
#[inline]
pub fn get_reprel_len(&self) -> Result<u64, Error> {
let txn = self.env.read_txn()?;
Ok(self.db_reprel()?.len(&txn)?)
}
/// The number of records in the people table
#[inline]
pub fn get_people_len(&self) -> Result<u64, Error> {
@ -1694,6 +1708,24 @@ impl Storage {
self.find_relationships1(id)
}
/// Write a relationship between an event and an EventAddr (replaceable)
#[inline]
pub(crate) fn write_reprel<'a>(
&'a self,
addr: EventAddr,
related: Id,
relationship: Relationship,
rw_txn: Option<&mut RwTxn<'a>>,
) -> Result<(), Error> {
self.write_reprel1(addr, related, relationship, rw_txn)
}
/// Find relationships belonging to the given event to replaceable events
#[inline]
pub fn find_reprels(&self, addr: &EventAddr) -> Result<Vec<(Id, Relationship)>, Error> {
self.find_reprels1(addr)
}
/// Get replies to the given event
pub fn get_replies(&self, id: Id) -> Result<Vec<Id>, Error> {
Ok(self
@ -1709,6 +1741,9 @@ impl Storage {
.collect())
}
// Get replies to the given EventAddr
// TODO
/// Returns the list of reactions and whether or not this account has already reacted to this event
pub fn get_reactions(&self, id: Id) -> Result<(Vec<(char, usize)>, bool), Error> {
// Whether or not the Gossip user already reacted to this event

View File

@ -0,0 +1,123 @@
use crate::error::Error;
use crate::relationship::Relationship;
use crate::storage::{RawDatabase, Storage};
use heed::RwTxn;
use heed::{types::UnalignedSlice, DatabaseFlags};
use nostr_types::{EventAddr, Id};
use speedy::{Readable, Writable};
use std::sync::Mutex;
// Kind:Pubkey:d-tag -> Relationship:Id
static REPREL1_DB_CREATE_LOCK: Mutex<()> = Mutex::new(());
static mut REPREL1_DB: Option<RawDatabase> = None;
impl Storage {
pub(super) fn db_reprel1(&self) -> Result<RawDatabase, Error> {
unsafe {
if let Some(db) = REPREL1_DB {
Ok(db)
} else {
// Lock. This drops when anything returns.
let _lock = REPREL1_DB_CREATE_LOCK.lock();
// In case of a race, check again
if let Some(db) = REPREL1_DB {
return Ok(db);
}
// Create it. We know that nobody else is doing this and that
// it cannot happen twice.
let mut txn = self.env.write_txn()?;
let db = self
.env
.database_options()
.types::<UnalignedSlice<u8>, UnalignedSlice<u8>>()
.flags(DatabaseFlags::DUP_SORT) // NOT FIXED, Relationship serialized isn't.
.name("reprel1")
.create(&mut txn)?;
txn.commit()?;
REPREL1_DB = Some(db);
Ok(db)
}
}
}
pub(crate) fn write_reprel1<'a>(
&'a self,
addr: EventAddr,
related: Id,
relationship: Relationship,
rw_txn: Option<&mut RwTxn<'a>>,
) -> Result<(), Error> {
let key = reprel1_into_key(&addr);
let value = reprel1_into_value(relationship, related)?;
let f = |txn: &mut RwTxn<'a>| -> Result<(), Error> {
self.db_reprel1()?.put(txn, &key, &value)?;
Ok(())
};
match rw_txn {
Some(txn) => f(txn)?,
None => {
let mut txn = self.env.write_txn()?;
f(&mut txn)?;
txn.commit()?;
}
};
Ok(())
}
pub(crate) fn find_reprels1(&self, addr: &EventAddr) -> Result<Vec<(Id, Relationship)>, Error> {
let key = reprel1_into_key(addr);
let txn = self.env.read_txn()?;
let iter = match self.db_reprel1()?.get_duplicates(&txn, &key)? {
Some(iter) => iter,
None => return Ok(vec![]),
};
let mut output: Vec<(Id, Relationship)> = Vec::new();
for result in iter {
let (_key, val) = result?;
let (rel, id) = reprel1_from_value(val)?;
output.push((id, rel));
}
Ok(output)
}
}
fn reprel1_into_key(ea: &EventAddr) -> Vec<u8> {
let u: u32 = ea.kind.into();
let mut key: Vec<u8> = u.to_be_bytes().as_slice().to_owned();
key.extend(ea.author.as_bytes());
key.extend(ea.d.as_bytes());
key
}
/*
fn reprel1_from_key(key: &[u8]) -> Result<EventAddr, Error> {
let u = u32::from_be_bytes(key[..4].try_into().unwrap());
let kind: EventKind = u.into();
let pubkey: PublicKey = PublicKey::from_bytes(&key[4..4+32], true)?;
let d: String = String::from_utf8_lossy(&key[4+32..]).to_string();
Ok(EventAddr {
d,
relays: vec![],
kind,
author: pubkey
})
}
*/
fn reprel1_into_value(relationship: Relationship, id: Id) -> Result<Vec<u8>, Error> {
let mut value: Vec<u8> = relationship.write_to_vec()?;
value.extend(id.as_slice());
Ok(value)
}
fn reprel1_from_value(value: &[u8]) -> Result<(Relationship, Id), Error> {
let (result, len) = Relationship::read_with_length_from_buffer(value);
let relationship = result?;
let id = Id(value[len..len + 32].try_into().unwrap());
Ok((relationship, id))
}