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,
 | 
			
		||||
    sync::{mpsc, oneshot},
 | 
			
		||||
};
 | 
			
		||||
use tracing::{error, info, info_span, instrument};
 | 
			
		||||
use tracing::{debug, error, info, info_span, instrument};
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    login::{self, database::LoginStatus},
 | 
			
		||||
| 
						 | 
				
			
			@ -370,6 +370,7 @@ impl SessionLoop {
 | 
			
		|||
                top_left,
 | 
			
		||||
                bottom_right,
 | 
			
		||||
            } => {
 | 
			
		||||
                debug!(?top_left, ?bottom_right, "Request::Viewport");
 | 
			
		||||
                self.viewport_chunks = ChunkIterator::new(top_left, bottom_right);
 | 
			
		||||
                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
 | 
			
		||||
            // stall the server by sending in a huge viewport.
 | 
			
		||||
            debug!(?self.viewport_chunks, ?self.sent_chunks);
 | 
			
		||||
            for _ in 0..9000 {
 | 
			
		||||
                if let Some(position) = self.viewport_chunks.next() {
 | 
			
		||||
                    if !self.sent_chunks.insert(position)
 | 
			
		||||
                        || !self.chunk_images.chunk_exists(position)
 | 
			
		||||
                    {
 | 
			
		||||
                    let sent = !self.sent_chunks.insert(position);
 | 
			
		||||
                    if sent || !self.chunk_images.chunk_exists(position) {
 | 
			
		||||
                        debug!(?position, "skipping chunk");
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    positions.push(position);
 | 
			
		||||
| 
						 | 
				
			
			@ -404,6 +406,8 @@ impl SessionLoop {
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            debug!(num = positions.len(), "pending chunk images");
 | 
			
		||||
 | 
			
		||||
            self.pending_images
 | 
			
		||||
                .extend(self.chunk_images.encoded(positions).await.data);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,13 @@ impl Broker {
 | 
			
		|||
                    default_wall_settings: self.settings.default_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(
 | 
			
		||||
                    Arc::clone(&wall),
 | 
			
		||||
                    Arc::clone(&chunk_images),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,10 +5,16 @@ use eyre::Context;
 | 
			
		|||
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
 | 
			
		||||
use tiny_skia::{IntSize, Pixmap};
 | 
			
		||||
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};
 | 
			
		||||
 | 
			
		||||
/// 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.
 | 
			
		||||
pub struct ChunkImages {
 | 
			
		||||
    wall: Arc<Wall>,
 | 
			
		||||
| 
						 | 
				
			
			@ -48,13 +54,13 @@ enum Command {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
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 async_loop = Arc::new(ChunkImageLoop {
 | 
			
		||||
            wall: Arc::clone(&wall),
 | 
			
		||||
            db,
 | 
			
		||||
            chunks_in_db: DashSet::new(),
 | 
			
		||||
            chunks_in_db: population.chunks_in_db,
 | 
			
		||||
        });
 | 
			
		||||
        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 {
 | 
			
		||||
        let (tx, rx) = oneshot::channel();
 | 
			
		||||
        _ = self
 | 
			
		||||
| 
						 | 
				
			
			@ -233,14 +250,7 @@ impl ChunkImageLoop {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    async fn enter(self: Arc<Self>, mut commands_rx: mpsc::Receiver<Command>) {
 | 
			
		||||
        let all_chunks = self
 | 
			
		||||
            .db
 | 
			
		||||
            .get_all_chunks()
 | 
			
		||||
            .await
 | 
			
		||||
            .expect("could not list chunks in the database");
 | 
			
		||||
        for position in all_chunks {
 | 
			
		||||
            self.chunks_in_db.insert(position);
 | 
			
		||||
        }
 | 
			
		||||
        debug!(num = ?self.chunks_in_db.len(), "chunks in database");
 | 
			
		||||
 | 
			
		||||
        while let Some(command) = commands_rx.recv().await {
 | 
			
		||||
            match command {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue