New settings: num_relays_per_person, max_relays (with new relay picker logic)

This commit is contained in:
Mike Dilger 2022-12-27 16:39:34 +13:00
parent c8c6fb04af
commit 8e95ccab00
6 changed files with 94 additions and 15 deletions

View File

@ -107,7 +107,7 @@ fn upgrade(db: &Connection, mut version: u16) -> Result<(), Error> {
apply_sql!(db, version, 2, "schema2.sql");
apply_sql!(db, version, 3, "schema3.sql");
apply_sql!(db, version, 4, "schema4.sql");
apply_sql!(db, version, 5, "schema5.sql");
info!("Database is at version {}", version);
Ok(())
}

2
src/db/schema5.sql Normal file
View File

@ -0,0 +1,2 @@
INSERT INTO settings (key, value) values ('num_relays_per_person', '2');
INSERT INTO settings (key, value) values ('max_relays', '15');

View File

@ -174,16 +174,37 @@ impl Overlord {
// Pick Relays and start Minions
{
let pubkeys: Vec<PublicKeyHex> = crate::globals::followed_pubkeys().await;
let num_relays_per_person = GLOBALS.settings.lock().await.num_relays_per_person;
let max_relays = GLOBALS.settings.lock().await.max_relays;
let mut pubkey_counts: HashMap<PublicKeyHex, u8> = HashMap::new();
for pk in pubkeys.iter() {
pubkey_counts.insert(pk.clone(), num_relays_per_person);
}
let mut relay_picker = RelayPicker {
relays: all_relays,
pubkeys: pubkeys.clone(),
pubkey_counts,
person_relays: DbPersonRelay::fetch_for_pubkeys(&pubkeys).await?,
};
let mut best_relay: BestRelay;
let mut relay_count = 0;
loop {
if relay_count >= max_relays {
warn!(
"Safety catch: we have picked {} relays. That's enough.",
max_relays
);
break;
}
if relay_picker.is_degenerate() {
info!(
"Relay picker is degenerate, relays={} pubkey_counts={}, person_relays={}",
relay_picker.relays.len(),
relay_picker.pubkey_counts.len(),
relay_picker.person_relays.len()
);
break;
}
@ -192,6 +213,7 @@ impl Overlord {
relay_picker = rp;
if best_relay.is_degenerate() {
info!("Best relay is now degenerate.");
break;
}
@ -206,11 +228,15 @@ impl Overlord {
});
info!(
"Picked relay {}, {} people left",
"Picked relay {} covering {} people.",
&best_relay.relay.url,
relay_picker.pubkeys.len()
best_relay.pubkeys.len()
);
relay_count += 1;
}
info!("Listening on {} relays", relay_count);
}
// Get desired events from relays

View File

@ -1,18 +1,19 @@
use crate::db::{DbPersonRelay, DbRelay};
use crate::error::Error;
use nostr_types::PublicKeyHex;
use std::collections::HashMap;
use tracing::info;
/// See RelayPicker::best()
pub struct RelayPicker {
pub relays: Vec<DbRelay>,
pub pubkeys: Vec<PublicKeyHex>,
pub pubkey_counts: HashMap<PublicKeyHex, u8>,
pub person_relays: Vec<DbPersonRelay>,
}
impl RelayPicker {
pub fn is_degenerate(&self) -> bool {
self.relays.is_empty() || self.pubkeys.is_empty() || self.person_relays.is_empty()
self.relays.is_empty() || self.pubkey_counts.is_empty() || self.person_relays.is_empty()
}
/// This function takes a RelayPicker which consists of a list of relays,
@ -21,7 +22,7 @@ impl RelayPicker {
/// the public keys such a relay will cover. It also outpus a new RelayPicker
/// that contains only the remaining relays and public keys.
pub fn best(mut self) -> Result<(BestRelay, RelayPicker), Error> {
if self.pubkeys.is_empty() {
if self.pubkey_counts.is_empty() {
return Err(Error::General(
"best_relay called for zero people".to_owned(),
));
@ -35,7 +36,7 @@ impl RelayPicker {
info!(
"Searching for the best relay among {} for {} people",
self.relays.len(),
self.pubkeys.len()
self.pubkey_counts.len()
);
// Keep score
@ -57,7 +58,7 @@ impl RelayPicker {
// Multiply scores by relay rank
#[allow(clippy::needless_range_loop)]
for i in 0..self.relays.len() {
score[i] *= self.relays[i].rank.unwrap_or(1);
score[i] *= self.relays[i].rank.unwrap_or(3);
}
let winner_index = score
@ -76,12 +77,30 @@ impl RelayPicker {
.map(|x| PublicKeyHex(x.person.clone()))
.collect();
self.pubkeys.retain(|x| !covered_public_keys.contains(x));
// Decrement entries where we found another relay for them
let mut changed = false;
for (pubkey, count) in self.pubkey_counts.iter_mut() {
if covered_public_keys.contains(pubkey) {
*count -= 1;
changed = true;
}
}
self.person_relays.retain(|pr| {
!covered_public_keys.contains(&PublicKeyHex(pr.person.clone()))
&& pr.relay != winner.url
});
// If the pubkey_counts did not change
if !changed {
// then we are now degenerate.
// Output a BestRelay with zero public keys to signal this
return Ok((
BestRelay {
relay: winner,
pubkeys: vec![],
},
self,
));
}
// Remove entries with 0 more relays needed
self.pubkey_counts.retain(|_, v| *v > 0);
Ok((
BestRelay {

View File

@ -8,6 +8,8 @@ pub const DEFAULT_AUTOFOLLOW: bool = false;
pub const DEFAULT_VIEW_POSTS_REFERRED_TO: bool = true;
pub const DEFAULT_VIEW_POSTS_REFERRING_TO: bool = false;
pub const DEFAULT_VIEW_THREADED: bool = true;
pub const DEFAULT_NUM_RELAYS_PER_PERSON: u8 = 2;
pub const DEFAULT_MAX_RELAYS: u8 = 15;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Settings {
@ -19,6 +21,8 @@ pub struct Settings {
pub view_posts_referred_to: bool,
pub view_posts_referring_to: bool,
pub view_threaded: bool,
pub num_relays_per_person: u8,
pub max_relays: u8,
}
impl Default for Settings {
@ -30,6 +34,8 @@ impl Default for Settings {
view_posts_referred_to: DEFAULT_VIEW_POSTS_REFERRED_TO,
view_posts_referring_to: DEFAULT_VIEW_POSTS_REFERRING_TO,
view_threaded: DEFAULT_VIEW_THREADED,
num_relays_per_person: DEFAULT_NUM_RELAYS_PER_PERSON,
max_relays: DEFAULT_MAX_RELAYS,
}
}
}
@ -60,6 +66,13 @@ impl Settings {
settings.view_posts_referring_to = numstr_to_bool(row.1)
}
"view_threaded" => settings.view_threaded = numstr_to_bool(row.1),
"num_relays_per_person" => {
settings.num_relays_per_person =
row.1.parse::<u8>().unwrap_or(DEFAULT_NUM_RELAYS_PER_PERSON)
}
"max_relays" => {
settings.max_relays = row.1.parse::<u8>().unwrap_or(DEFAULT_MAX_RELAYS)
}
_ => {}
}
}
@ -75,7 +88,8 @@ impl Settings {
"REPLACE INTO settings (key, value) VALUES \
('feed_chunk', ?),('overlap', ?),('autofollow', ?),\
('view_posts_referred_to', ?),('view_posts_referring_to', ?),\
('view_threaded', ?)",
('view_threaded', ?),('num_relays_per_person', ?), \
('max_relays', ?)",
)?;
stmt.execute((
self.feed_chunk,
@ -92,6 +106,8 @@ impl Settings {
"0"
},
if self.view_threaded { "1" } else { "0" },
self.num_relays_per_person,
self.max_relays,
))?;
Ok(())

View File

@ -16,6 +16,22 @@ pub(super) fn update(
ui.separator();
ui.add_space(24.0);
ui.heading("How Many Relays to Query");
ui.horizontal(|ui| {
ui.label("Number of relays to query per person: ").on_hover_text("We will query N relays per person. Many people share the same relays so those will be queried about multiple people. Takes affect on restart.");
ui.add(Slider::new(&mut app.settings.num_relays_per_person, 1..=5).text("relays"));
});
ui.horizontal(|ui| {
ui.label("Maximum total number of relays to query: ")
.on_hover_text(
"We will not connect to more than this many relays. Takes affect on restart.",
);
ui.add(Slider::new(&mut app.settings.max_relays, 1..=30).text("relays"));
});
ui.add_space(24.0);
ui.heading("How Many Posts to Load");