fix chunk images not being populated when the first client joins the room
This commit is contained in:
parent
e9f9e21bc2
commit
8e467d5447
3 changed files with 36 additions and 16 deletions
|
@ -25,7 +25,7 @@ use tokio::{
|
||||||
select,
|
select,
|
||||||
sync::{mpsc, oneshot},
|
sync::{mpsc, oneshot},
|
||||||
};
|
};
|
||||||
use tracing::{error, info, info_span, instrument};
|
use tracing::{debug, error, info, info_span, instrument};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
login::{self, database::LoginStatus},
|
login::{self, database::LoginStatus},
|
||||||
|
@ -370,6 +370,7 @@ impl SessionLoop {
|
||||||
top_left,
|
top_left,
|
||||||
bottom_right,
|
bottom_right,
|
||||||
} => {
|
} => {
|
||||||
|
debug!(?top_left, ?bottom_right, "Request::Viewport");
|
||||||
self.viewport_chunks = ChunkIterator::new(top_left, bottom_right);
|
self.viewport_chunks = ChunkIterator::new(top_left, bottom_right);
|
||||||
self.send_chunks(ws).await?;
|
self.send_chunks(ws).await?;
|
||||||
}
|
}
|
||||||
|
@ -391,11 +392,12 @@ impl SessionLoop {
|
||||||
|
|
||||||
// Number of chunks iterated is limited per packet, so as not to let the client
|
// Number of chunks iterated is limited per packet, so as not to let the client
|
||||||
// stall the server by sending in a huge viewport.
|
// stall the server by sending in a huge viewport.
|
||||||
|
debug!(?self.viewport_chunks, ?self.sent_chunks);
|
||||||
for _ in 0..9000 {
|
for _ in 0..9000 {
|
||||||
if let Some(position) = self.viewport_chunks.next() {
|
if let Some(position) = self.viewport_chunks.next() {
|
||||||
if !self.sent_chunks.insert(position)
|
let sent = !self.sent_chunks.insert(position);
|
||||||
|| !self.chunk_images.chunk_exists(position)
|
if sent || !self.chunk_images.chunk_exists(position) {
|
||||||
{
|
debug!(?position, "skipping chunk");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
positions.push(position);
|
positions.push(position);
|
||||||
|
@ -404,6 +406,8 @@ impl SessionLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!(num = positions.len(), "pending chunk images");
|
||||||
|
|
||||||
self.pending_images
|
self.pending_images
|
||||||
.extend(self.chunk_images.encoded(positions).await.data);
|
.extend(self.chunk_images.encoded(positions).await.data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,13 @@ impl Broker {
|
||||||
default_wall_settings: self.settings.default_wall_settings,
|
default_wall_settings: self.settings.default_wall_settings,
|
||||||
})?);
|
})?);
|
||||||
let wall = Arc::new(Wall::new(*db.wall_settings()));
|
let wall = Arc::new(Wall::new(*db.wall_settings()));
|
||||||
let chunk_images = Arc::new(ChunkImages::new(Arc::clone(&wall), Arc::clone(&db)));
|
let chunk_images = Arc::new(ChunkImages::new(
|
||||||
|
Arc::clone(&wall),
|
||||||
|
Arc::clone(&db),
|
||||||
|
// NOTE: Upon initial loading, this will stall until the query finishes.
|
||||||
|
// This is probably very sub-optimal on walls with a lot of chunks.
|
||||||
|
ChunkImages::populate(&db).await,
|
||||||
|
));
|
||||||
let auto_save = Arc::new(AutoSave::new(
|
let auto_save = Arc::new(AutoSave::new(
|
||||||
Arc::clone(&wall),
|
Arc::clone(&wall),
|
||||||
Arc::clone(&chunk_images),
|
Arc::clone(&chunk_images),
|
||||||
|
|
|
@ -5,10 +5,16 @@ use eyre::Context;
|
||||||
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
use tiny_skia::{IntSize, Pixmap};
|
use tiny_skia::{IntSize, Pixmap};
|
||||||
use tokio::sync::{mpsc, oneshot, Mutex};
|
use tokio::sync::{mpsc, oneshot, Mutex};
|
||||||
use tracing::{error, info, instrument};
|
use tracing::{debug, error, info, instrument};
|
||||||
|
|
||||||
use super::{database::ChunkDataPair, Chunk, ChunkPosition, Database, Wall};
|
use super::{database::ChunkDataPair, Chunk, ChunkPosition, Database, Wall};
|
||||||
|
|
||||||
|
/// Initial population of `ChunkImages`'s cache.
|
||||||
|
/// Created as part of an async process before `new`.
|
||||||
|
pub struct Population {
|
||||||
|
chunks_in_db: DashSet<ChunkPosition>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Chunk image encoding, caching, and storage service.
|
/// Chunk image encoding, caching, and storage service.
|
||||||
pub struct ChunkImages {
|
pub struct ChunkImages {
|
||||||
wall: Arc<Wall>,
|
wall: Arc<Wall>,
|
||||||
|
@ -48,13 +54,13 @@ enum Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChunkImages {
|
impl ChunkImages {
|
||||||
pub fn new(wall: Arc<Wall>, db: Arc<Database>) -> Self {
|
pub fn new(wall: Arc<Wall>, db: Arc<Database>, population: Population) -> Self {
|
||||||
let (commands_tx, commands_rx) = mpsc::channel(32);
|
let (commands_tx, commands_rx) = mpsc::channel(32);
|
||||||
|
|
||||||
let async_loop = Arc::new(ChunkImageLoop {
|
let async_loop = Arc::new(ChunkImageLoop {
|
||||||
wall: Arc::clone(&wall),
|
wall: Arc::clone(&wall),
|
||||||
db,
|
db,
|
||||||
chunks_in_db: DashSet::new(),
|
chunks_in_db: population.chunks_in_db,
|
||||||
});
|
});
|
||||||
tokio::spawn(Arc::clone(&async_loop).enter(commands_rx));
|
tokio::spawn(Arc::clone(&async_loop).enter(commands_rx));
|
||||||
|
|
||||||
|
@ -65,6 +71,17 @@ impl ChunkImages {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn populate(db: &Database) -> Population {
|
||||||
|
Population {
|
||||||
|
chunks_in_db: db
|
||||||
|
.get_all_chunks()
|
||||||
|
.await
|
||||||
|
.expect("could not list chunks in the database")
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn encoded(&self, chunks: Vec<ChunkPosition>) -> EncodeResult {
|
pub async fn encoded(&self, chunks: Vec<ChunkPosition>) -> EncodeResult {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
_ = self
|
_ = self
|
||||||
|
@ -233,14 +250,7 @@ impl ChunkImageLoop {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn enter(self: Arc<Self>, mut commands_rx: mpsc::Receiver<Command>) {
|
async fn enter(self: Arc<Self>, mut commands_rx: mpsc::Receiver<Command>) {
|
||||||
let all_chunks = self
|
debug!(num = ?self.chunks_in_db.len(), "chunks in database");
|
||||||
.db
|
|
||||||
.get_all_chunks()
|
|
||||||
.await
|
|
||||||
.expect("could not list chunks in the database");
|
|
||||||
for position in all_chunks {
|
|
||||||
self.chunks_in_db.insert(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
while let Some(command) = commands_rx.recv().await {
|
while let Some(command) = commands_rx.recv().await {
|
||||||
match command {
|
match command {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue