Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9ec66bd
Initial plan
Copilot Feb 11, 2026
43f6e3e
Implement etag plumbing for mbtiles backend
Copilot Feb 11, 2026
1d3ff6b
Address code review feedback
Copilot Feb 11, 2026
46dab12
Apply suggestion from @CommanderStorm
CommanderStorm Feb 11, 2026
01ff249
Fix CI test failures by making MbtType detection optional
Copilot Feb 11, 2026
c82ab86
Remove inefficient fallback logic and fix test fixture
Copilot Feb 12, 2026
9417b26
Merge branch 'main' into copilot/optimize-etag-implementation
CommanderStorm Feb 12, 2026
57a0738
Delete tests/fixtures/mbtiles/webp_valid.sql
CommanderStorm Feb 12, 2026
3ba880a
add an webp index
CommanderStorm Feb 12, 2026
defd30c
Apply suggestion from @CommanderStorm
CommanderStorm Feb 12, 2026
83911ab
Update tests/fixtures/mbtiles/webp.sql
CommanderStorm Feb 12, 2026
a71792a
Update martin-core/src/tiles/mbtiles/source.rs
CommanderStorm Feb 12, 2026
d63b51e
Fix error handling to preserve AcquireConnError for SqlxError
Copilot Feb 12, 2026
0199c66
Merge branch 'main' into copilot/optimize-etag-implementation
CommanderStorm Feb 12, 2026
950e5ab
Update martin-core/src/tiles/mbtiles/source.rs
CommanderStorm Feb 12, 2026
60cb46a
Update martin-core/src/tiles/mbtiles/source.rs
CommanderStorm Feb 12, 2026
0879df1
Update martin-core/src/tiles/mbtiles/source.rs
CommanderStorm Feb 12, 2026
eca0bc4
Refactor error handling into helper function
Copilot Feb 12, 2026
de1dc2e
Apply suggestions from code review
CommanderStorm Feb 12, 2026
5406a7f
Apply suggestion from @CommanderStorm
CommanderStorm Feb 12, 2026
e89a53a
Apply suggestion from @CommanderStorm
CommanderStorm Feb 12, 2026
656960f
chore(fmt): apply pre-commit formatting fixes
pre-commit-ci[bot] Feb 12, 2026
574fe0d
Merge branch 'main' into copilot/optimize-etag-implementation
nyurik Feb 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 45 additions & 4 deletions martin-core/src/tiles/mbtiles/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use std::sync::Arc;

use async_trait::async_trait;
use martin_tile_utils::{TileCoord, TileData, TileInfo};
use mbtiles::{MbtError, MbtilesPool};
use mbtiles::{MbtError, MbtType, MbtilesPool};
use tilejson::TileJSON;
use tracing::trace;

use crate::tiles::mbtiles::MbtilesError;
use crate::tiles::{BoxedSource, MartinCoreResult, Source, UrlQuery};
use crate::tiles::{BoxedSource, MartinCoreResult, Source, Tile, UrlQuery};

/// Tile source that reads from `MBTiles` files.
#[derive(Clone)]
Expand All @@ -21,6 +21,7 @@ pub struct MbtSource {
mbtiles: Arc<MbtilesPool>,
tilejson: TileJSON,
tile_info: TileInfo,
mbt_type: MbtType,
}

#[expect(clippy::missing_fields_in_debug)]
Expand All @@ -29,6 +30,7 @@ impl Debug for MbtSource {
f.debug_struct("MbtSource")
.field("id", &self.id)
.field("path", &self.mbtiles.as_ref())
.field("mbt_type", &self.mbt_type)
.finish()
}
}
Expand All @@ -51,15 +53,29 @@ impl MbtSource {
.detect_format(&meta.tilejson)
.await
.and_then(|v| v.ok_or(MbtError::NoTilesFound))
.map_err(|e| MbtilesError::InvalidMetadata(e.to_string(), path))?;
.map_err(|e| MbtilesError::InvalidMetadata(e.to_string(), path.clone()))?;

let mbt_type = mbt
.detect_type()
.await
.map_err(|e| MbtilesError::InvalidMetadata(e.to_string(), path.clone()))?;

Ok(Self {
id,
mbtiles: Arc::new(mbt),
tilejson: meta.tilejson,
tile_info,
mbt_type,
})
}

/// Maps `MbtError` to `MbtilesError`, preserving source ID context for `SqlxError`.
fn map_mbt_error(error: MbtError, id: String) -> MbtilesError {
match error {
MbtError::SqlxError(_) => MbtilesError::AcquireConnError(id),
other => MbtilesError::MbtilesLibraryError(other),
}
}
}

#[async_trait]
Expand Down Expand Up @@ -98,7 +114,7 @@ impl Source for MbtSource {
.mbtiles
.get_tile(xyz.z, xyz.x, xyz.y)
.await
.map_err(|_| MbtilesError::AcquireConnError(self.id.clone()))?
.map_err(|e| Self::map_mbt_error(e, self.id.clone()))?
{
Ok(tile)
} else {
Expand All @@ -109,4 +125,29 @@ impl Source for MbtSource {
Ok(Vec::new())
}
}

async fn get_tile_with_etag(
&self,
xyz: TileCoord,
_url_query: Option<&UrlQuery>,
) -> MartinCoreResult<Tile> {
if let Some((data, hash)) = self
.mbtiles
.get_tile_and_hash(self.mbt_type, xyz.z, xyz.x, xyz.y)
.await
.map_err(|e| Self::map_mbt_error(e, self.id.clone()))?
{
if let Some(hash_str) = hash {
Ok(Tile::new_with_etag(data, self.tile_info, hash_str))
} else {
Ok(Tile::new_hash_etag(data, self.tile_info))
}
} else {
trace!(
"Couldn't find tile data in {}/{}/{} of {}",
xyz.z, xyz.x, xyz.y, &self.id
);
Ok(Tile::new_hash_etag(Vec::new(), self.tile_info))
}
}
}
8 changes: 4 additions & 4 deletions tests/fixtures/mbtiles/webp.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ INSERT INTO metadata VALUES
('center','0,0,0'),
('minzoom','0'),
('maxzoom','0');
CREATE TABLE IF NOT EXISTS "tiles"(
zoom_level int,
tile_column int,
tile_row int,
CREATE TABLE tiles (
zoom_level integer,
tile_column integer,
tile_row integer,
tile_data blob
);
INSERT INTO tiles VALUES(0,0,0,x'524946463A000000574542505650380A0000002F000000');
Expand Down
Loading