refactor/tighten-architecture #26

Merged
GKaszewski merged 104 commits from refactor/tighten-architecture into master 2026-10-26 09:36:27 +00:00
62 changed files with 292 additions and 442 deletions
Showing only changes of commit 67597ec9a6 - Show all commits

View File

@@ -44,4 +44,4 @@ jobs:
# Layering guards. These live in the Makefile and were previously local-only, # Layering guards. These live in the Makefile and were previously local-only,
# so a PR could go green in CI while violating them. # so a PR could go green in CI while violating them.
- name: guards - name: guards
run: make check-appcontext check-handler-deps check-handler-repos check-presentation-adapters check-federation-off-social check-social-crates-are-ap-free run: make check-appcontext check-handler-deps check-handler-repos check-presentation-adapters check-federation-off-social check-sqlite-is-ap-free

View File

@@ -44,7 +44,7 @@ jobs:
# Layering guards. These live in the Makefile and were previously local-only, # Layering guards. These live in the Makefile and were previously local-only,
# so a PR could go green in CI while violating them. # so a PR could go green in CI while violating them.
- name: guards - name: guards
run: make check-appcontext check-handler-deps check-handler-repos check-presentation-adapters check-federation-off-social check-social-crates-are-ap-free run: make check-appcontext check-handler-deps check-handler-repos check-presentation-adapters check-federation-off-social check-sqlite-is-ap-free
docker: docker:
name: Build & Push Docker Image name: Build & Push Docker Image

66
Cargo.lock generated
View File

@@ -220,17 +220,6 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "adapter-common"
version = "0.1.0"
dependencies = [
"chrono",
"domain",
"sqlx",
"tracing",
"uuid",
]
[[package]] [[package]]
name = "adler2" name = "adler2"
version = "2.0.1" version = "2.0.1"
@@ -1148,10 +1137,7 @@ dependencies = [
"plex", "plex",
"poster-fetcher", "poster-fetcher",
"sqlite", "sqlite",
"sqlite-event-queue",
"sqlite-federation", "sqlite-federation",
"sqlite-search",
"sqlite-social",
"sqlx", "sqlx",
"tokio", "tokio",
"tracing", "tracing",
@@ -4950,10 +4936,7 @@ dependencies = [
"rss 0.1.0", "rss 0.1.0",
"serde_json", "serde_json",
"sqlite", "sqlite",
"sqlite-event-queue",
"sqlite-federation", "sqlite-federation",
"sqlite-search",
"sqlite-social",
"sqlx", "sqlx",
"tokio", "tokio",
"tower", "tower",
@@ -5195,18 +5178,16 @@ dependencies = [
name = "sqlite" name = "sqlite"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"adapter-common",
"anyhow", "anyhow",
"async-stream", "async-stream",
"async-trait", "async-trait",
"bytes", "bytes",
"chrono", "chrono",
"domain", "domain",
"event-payload",
"futures", "futures",
"serde", "serde",
"serde_json", "serde_json",
"sqlite-event-queue",
"sqlite-social",
"sqlx", "sqlx",
"tempfile", "tempfile",
"tokio", "tokio",
@@ -5214,65 +5195,24 @@ dependencies = [
"uuid", "uuid",
] ]
[[package]]
name = "sqlite-event-queue"
version = "0.1.0"
dependencies = [
"anyhow",
"async-trait",
"domain",
"event-payload",
"futures",
"serde_json",
"sqlx",
"tokio",
"tracing",
]
[[package]] [[package]]
name = "sqlite-federation" name = "sqlite-federation"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"activitypub", "activitypub",
"adapter-common",
"anyhow", "anyhow",
"async-trait", "async-trait",
"chrono", "chrono",
"domain", "domain",
"k-ap", "k-ap",
"serde_json", "serde_json",
"sqlite-social", "sqlite",
"sqlx", "sqlx",
"tokio", "tokio",
"tracing", "tracing",
"uuid", "uuid",
] ]
[[package]]
name = "sqlite-search"
version = "0.1.0"
dependencies = [
"adapter-common",
"async-trait",
"domain",
"sqlx",
"tokio",
"uuid",
]
[[package]]
name = "sqlite-social"
version = "0.1.0"
dependencies = [
"adapter-common",
"async-trait",
"chrono",
"domain",
"sqlx",
"tokio",
"uuid",
]
[[package]] [[package]]
name = "sqlx" name = "sqlx"
version = "0.8.6" version = "0.8.6"
@@ -7206,9 +7146,7 @@ dependencies = [
"poster-fetcher", "poster-fetcher",
"poster-sync", "poster-sync",
"sqlite", "sqlite",
"sqlite-event-queue",
"sqlite-federation", "sqlite-federation",
"sqlite-search",
"sqlx", "sqlx",
"tmdb-enrichment", "tmdb-enrichment",
"tokio", "tokio",

View File

@@ -9,8 +9,6 @@ members = [
"crates/adapters/rss", "crates/adapters/rss",
"crates/adapters/sqlite", "crates/adapters/sqlite",
"crates/adapters/sqlite-federation", "crates/adapters/sqlite-federation",
"crates/adapters/sqlite-social",
"crates/adapters/sqlite-event-queue",
"crates/adapters/template-askama", "crates/adapters/template-askama",
"crates/adapters/activitypub", "crates/adapters/activitypub",
"crates/adapters/export", "crates/adapters/export",
@@ -29,8 +27,6 @@ members = [
"crates/adapters/importer", "crates/adapters/importer",
"crates/adapters/jellyfin", "crates/adapters/jellyfin",
"crates/adapters/plex", "crates/adapters/plex",
"crates/adapters/sqlite-search",
"crates/adapters/adapter-common",
"crates/infra-wiring", "crates/infra-wiring",
] ]
resolver = "2" resolver = "2"
@@ -84,18 +80,14 @@ rss = { path = "crates/adapters/rss" }
export = { path = "crates/adapters/export" } export = { path = "crates/adapters/export" }
sqlite = { path = "crates/adapters/sqlite" } sqlite = { path = "crates/adapters/sqlite" }
sqlite-federation = { path = "crates/adapters/sqlite-federation" } sqlite-federation = { path = "crates/adapters/sqlite-federation" }
sqlite-social = { path = "crates/adapters/sqlite-social" }
template-askama = { path = "crates/adapters/template-askama" } template-askama = { path = "crates/adapters/template-askama" }
activitypub = { path = "crates/adapters/activitypub" } activitypub = { path = "crates/adapters/activitypub" }
event-payload = { path = "crates/adapters/event-payload" } event-payload = { path = "crates/adapters/event-payload" }
nats = { path = "crates/adapters/nats" } nats = { path = "crates/adapters/nats" }
sqlite-event-queue = { path = "crates/adapters/sqlite-event-queue" }
importer = { path = "crates/adapters/importer" } importer = { path = "crates/adapters/importer" }
jellyfin = { path = "crates/adapters/jellyfin" } jellyfin = { path = "crates/adapters/jellyfin" }
plex = { path = "crates/adapters/plex" } plex = { path = "crates/adapters/plex" }
image-converter = { path = "crates/adapters/image-converter" } image-converter = { path = "crates/adapters/image-converter" }
sqlite-search = { path = "crates/adapters/sqlite-search" }
adapter-common = { path = "crates/adapters/adapter-common" }
infra-wiring = { path = "crates/infra-wiring" } infra-wiring = { path = "crates/infra-wiring" }
[profile.dev] [profile.dev]

View File

@@ -34,8 +34,6 @@ COPY crates/adapters/plex/Cargo.toml crates/adapters/plex/Cargo.tom
COPY crates/adapters/rss/Cargo.toml crates/adapters/rss/Cargo.toml COPY crates/adapters/rss/Cargo.toml crates/adapters/rss/Cargo.toml
COPY crates/adapters/sqlite/Cargo.toml crates/adapters/sqlite/Cargo.toml COPY crates/adapters/sqlite/Cargo.toml crates/adapters/sqlite/Cargo.toml
COPY crates/adapters/sqlite-federation/Cargo.toml crates/adapters/sqlite-federation/Cargo.toml COPY crates/adapters/sqlite-federation/Cargo.toml crates/adapters/sqlite-federation/Cargo.toml
COPY crates/adapters/sqlite-social/Cargo.toml crates/adapters/sqlite-social/Cargo.toml
COPY crates/adapters/sqlite-event-queue/Cargo.toml crates/adapters/sqlite-event-queue/Cargo.toml
COPY crates/adapters/template-askama/Cargo.toml crates/adapters/template-askama/Cargo.toml COPY crates/adapters/template-askama/Cargo.toml crates/adapters/template-askama/Cargo.toml
COPY crates/api-types/Cargo.toml crates/api-types/Cargo.toml COPY crates/api-types/Cargo.toml crates/api-types/Cargo.toml
COPY crates/application/Cargo.toml crates/application/Cargo.toml COPY crates/application/Cargo.toml crates/application/Cargo.toml
@@ -46,8 +44,6 @@ COPY crates/presentation/Cargo.toml crates/presentation/Cargo.toml
COPY crates/server/Cargo.toml crates/server/Cargo.toml COPY crates/server/Cargo.toml crates/server/Cargo.toml
COPY crates/tui/Cargo.toml crates/tui/Cargo.toml COPY crates/tui/Cargo.toml crates/tui/Cargo.toml
COPY crates/adapters/image-converter/Cargo.toml crates/adapters/image-converter/Cargo.toml COPY crates/adapters/image-converter/Cargo.toml crates/adapters/image-converter/Cargo.toml
COPY crates/adapters/sqlite-search/Cargo.toml crates/adapters/sqlite-search/Cargo.toml
COPY crates/adapters/adapter-common/Cargo.toml crates/adapters/adapter-common/Cargo.toml
COPY crates/worker/Cargo.toml crates/worker/Cargo.toml COPY crates/worker/Cargo.toml crates/worker/Cargo.toml
COPY crates/infra-wiring/Cargo.toml crates/infra-wiring/Cargo.toml COPY crates/infra-wiring/Cargo.toml crates/infra-wiring/Cargo.toml

View File

@@ -1,6 +1,6 @@
.DEFAULT_GOAL := check .DEFAULT_GOAL := check
check: fmt-check clippy test check-appcontext check-handler-deps check-handler-repos check-presentation-adapters check-federation-off-social check-social-crates-are-ap-free check: fmt-check clippy test check-appcontext check-handler-deps check-handler-repos check-presentation-adapters check-federation-off-social check-sqlite-is-ap-free
@echo "✅ All checks passed" @echo "✅ All checks passed"
check-appcontext: check-appcontext:
@@ -59,13 +59,13 @@ check-federation-off-social:
@echo "✅ server wires real social behavior in every configuration" @echo "✅ server wires real social behavior in every configuration"
check-social-crates-are-ap-free: check-sqlite-is-ap-free:
@if grep -nE '^[[:space:]]*(k-ap|activitypub[A-Za-z0-9_-]*|[A-Za-z0-9_-]+-federation)[[:space:]]*=' crates/adapters/*-social/Cargo.toml | grep -q .; then \ @if grep -nE '^[[:space:]]*(k-ap|activitypub[A-Za-z0-9_-]*|[A-Za-z0-9_-]+-federation)[[:space:]]*=' crates/adapters/sqlite/Cargo.toml | grep -q .; then \
echo "❌ social crate depends on ActivityPub:"; \ echo "❌ sqlite crate depends on ActivityPub:"; \
grep -nE '^[[:space:]]*(k-ap|activitypub[A-Za-z0-9_-]*|[A-Za-z0-9_-]+-federation)[[:space:]]*=' crates/adapters/*-social/Cargo.toml; \ grep -nE '^[[:space:]]*(k-ap|activitypub[A-Za-z0-9_-]*|[A-Za-z0-9_-]+-federation)[[:space:]]*=' crates/adapters/sqlite/Cargo.toml; \
exit 1; \ exit 1; \
fi fi
@echo "✅ social crates depend on no k-ap, activitypub, or *-federation crate" @echo "✅ sqlite crate depends on no k-ap, activitypub, or *-federation crate"
fmt: fmt:
cargo fmt cargo fmt
@@ -106,4 +106,4 @@ dev-spa:
spa-dev: spa-dev:
@npm --prefix spa run dev @npm --prefix spa run dev
.PHONY: check fmt fmt-check clippy test fix dev dev-stop dev-worker dev-spa spa-dev check-appcontext check-handler-deps check-handler-repos check-presentation-adapters check-federation-off-social check-social-crates-are-ap-free .PHONY: check fmt fmt-check clippy test fix dev dev-stop dev-worker dev-spa spa-dev check-appcontext check-handler-deps check-handler-repos check-presentation-adapters check-federation-off-social check-sqlite-is-ap-free

View File

@@ -98,9 +98,8 @@ presentation — Axum HTTP router, OpenAPI spec assembly, Swagger UI + Sc
server — owns the HTTP binary, features (federation, nats), boots presentation's router server — owns the HTTP binary, features (federation, nats), boots presentation's router
worker — standalone worker binary (event consumer, poster sync, federation) worker — standalone worker binary (event consumer, poster sync, federation)
adapters/ adapters/
adapter-common — shared row-to-domain conversions, sqlx error mapping, date/uuid parsing utils
auth — JWT issuance and validation (Argon2 passwords) auth — JWT issuance and validation (Argon2 passwords)
sqlite — SQLite repository + connection factory sqlite — SQLite repositories, search (FTS5), social graph, durable event queue, connection factory + migrations
metadata — TMDB / OMDb HTTP client metadata — TMDB / OMDb HTTP client
poster-fetcher — downloads poster images poster-fetcher — downloads poster images
object-storage — stores images (posters + user avatars) on local filesystem or S3-compatible storage object-storage — stores images (posters + user avatars) on local filesystem or S3-compatible storage
@@ -114,11 +113,9 @@ adapters/
jellyfin — Jellyfin webhook payload parser (MediaServerParser adapter) jellyfin — Jellyfin webhook payload parser (MediaServerParser adapter)
plex — Plex webhook payload parser (MediaServerParser adapter; requires Plex Pass) plex — Plex webhook payload parser (MediaServerParser adapter; requires Plex Pass)
event-payload — shared event serialization DTOs (used by all event bus adapters) event-payload — shared event serialization DTOs (used by all event bus adapters)
sqlite-event-queue — durable polling event queue backed by SQLite
event-publisher — in-memory event channel (used in tests) event-publisher — in-memory event channel (used in tests)
nats — NATS Core / JetStream event publisher and consumer nats — NATS Core / JetStream event publisher and consumer
activitypub — ActivityPub federation adapter (follow, inbox/outbox, actor); delegates to k-ap for protocol internals activitypub — ActivityPub federation adapter (follow, inbox/outbox, actor); delegates to k-ap for protocol internals
sqlite-search — SQLite FTS5 implementation of SearchPort + SearchCommand
sqlite-federation — SQLite-backed federation repository sqlite-federation — SQLite-backed federation repository
tui — terminal UI client (ratatui); shares api-types with presentation for typed API access tui — terminal UI client (ratatui); shares api-types with presentation for typed API access
spa/ — React SPA (TanStack Router + shadcn/ui + Vite); served at /app/ by the backend spa/ — React SPA (TanStack Router + shadcn/ui + Vite); served at /app/ by the backend

View File

@@ -1,11 +0,0 @@
[package]
name = "adapter-common"
version = "0.1.0"
edition.workspace = true
[dependencies]
domain = { workspace = true }
sqlx = { workspace = true }
tracing = { workspace = true }
chrono = { workspace = true }
uuid = { workspace = true }

View File

@@ -1,15 +0,0 @@
[package]
name = "sqlite-event-queue"
version = "0.1.0"
edition.workspace = true
[dependencies]
sqlx = { workspace = true, features = ["macros", "chrono"] }
domain = { workspace = true }
event-payload = { workspace = true }
anyhow = { workspace = true }
async-trait = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }
futures = { workspace = true }
tracing = { workspace = true }

View File

@@ -1,7 +0,0 @@
pub(crate) async fn run(pool: &sqlx::SqlitePool) -> anyhow::Result<()> {
sqlx::migrate!("./migrations")
.set_ignore_missing(true)
.run(pool)
.await
.map_err(|e| anyhow::anyhow!("sqlite-event-queue migration failed: {e}"))
}

View File

@@ -6,9 +6,8 @@ edition.workspace = true
[dependencies] [dependencies]
sqlx = { workspace = true } sqlx = { workspace = true }
activitypub = { workspace = true } activitypub = { workspace = true }
adapter-common = { workspace = true }
k-ap = { version = "0.5.0", registry = "gitea" } k-ap = { version = "0.5.0", registry = "gitea" }
sqlite-social = { workspace = true } sqlite = { workspace = true }
domain = { workspace = true } domain = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }

View File

@@ -4,7 +4,7 @@ use chrono::Utc;
use k_ap::ActivityRepository; use k_ap::ActivityRepository;
use super::SqliteFederationRepository; use super::SqliteFederationRepository;
use adapter_common::datetime_to_str; use sqlite::persistence::datetime_to_str;
#[async_trait] #[async_trait]
impl ActivityRepository for SqliteFederationRepository { impl ActivityRepository for SqliteFederationRepository {

View File

@@ -5,7 +5,7 @@ use k_ap::{AnnounceRepository, Keypair, KeypairRepository, RemoteActor, RemoteAc
use sqlx::Row; use sqlx::Row;
use super::{SqliteFederationRepository, remote_actor_from_row}; use super::{SqliteFederationRepository, remote_actor_from_row};
use adapter_common::datetime_to_str; use sqlite::persistence::datetime_to_str;
#[async_trait] #[async_trait]
impl KeypairRepository for SqliteFederationRepository { impl KeypairRepository for SqliteFederationRepository {

View File

@@ -5,7 +5,7 @@ use k_ap::{ActorBlocklist, BlockedDomain, DomainBlocklist};
use sqlx::Row; use sqlx::Row;
use super::SqliteFederationRepository; use super::SqliteFederationRepository;
use adapter_common::datetime_to_str; use sqlite::persistence::datetime_to_str;
#[async_trait] #[async_trait]
impl DomainBlocklist for SqliteFederationRepository { impl DomainBlocklist for SqliteFederationRepository {

View File

@@ -5,7 +5,7 @@ use k_ap::{Follower, FollowerReader, FollowerStatus, FollowerWriter, RemoteActor
use sqlx::Row; use sqlx::Row;
use crate::{SqliteFederationRepository, remote_actor_from_row, status_to_str, str_to_status}; use crate::{SqliteFederationRepository, remote_actor_from_row, status_to_str, str_to_status};
use adapter_common::datetime_to_str; use sqlite::persistence::datetime_to_str;
#[async_trait] #[async_trait]
impl FollowerWriter for SqliteFederationRepository { impl FollowerWriter for SqliteFederationRepository {

View File

@@ -4,7 +4,7 @@ use chrono::Utc;
use k_ap::{FollowingReader, FollowingStatus, FollowingWriter, RemoteActor, RemoteActorCache}; use k_ap::{FollowingReader, FollowingStatus, FollowingWriter, RemoteActor, RemoteActorCache};
use crate::{SqliteFederationRepository, remote_actor_from_row}; use crate::{SqliteFederationRepository, remote_actor_from_row};
use adapter_common::datetime_to_str; use sqlite::persistence::datetime_to_str;
#[async_trait] #[async_trait]
impl FollowingWriter for SqliteFederationRepository { impl FollowingWriter for SqliteFederationRepository {

View File

@@ -79,7 +79,7 @@ pub fn wire(
instance: domain::value_objects::InstanceIdentity, instance: domain::value_objects::InstanceIdentity,
) -> activitypub::FederationRepos { ) -> activitypub::FederationRepos {
let fed = std::sync::Arc::new(SqliteFederationRepository::new(pool.clone())); let fed = std::sync::Arc::new(SqliteFederationRepository::new(pool.clone()));
let social = std::sync::Arc::new(sqlite_social::SqliteSocialRepository::new(pool, instance)); let social = std::sync::Arc::new(sqlite::SqliteSocialRepository::new(pool, instance));
activitypub::FederationRepos { activitypub::FederationRepos {
activity: std::sync::Arc::clone(&fed) as _, activity: std::sync::Arc::clone(&fed) as _,
follow: std::sync::Arc::clone(&fed) as _, follow: std::sync::Arc::clone(&fed) as _,

View File

@@ -4,7 +4,7 @@ use async_trait::async_trait;
use domain::models::{Review, ReviewSource}; use domain::models::{Review, ReviewSource};
use super::SqliteFederationRepository; use super::SqliteFederationRepository;
use adapter_common::datetime_to_str; use sqlite::persistence::datetime_to_str;
#[async_trait] #[async_trait]
impl RemoteReviewRepository for SqliteFederationRepository { impl RemoteReviewRepository for SqliteFederationRepository {

View File

@@ -1,14 +0,0 @@
[package]
name = "sqlite-search"
version = "0.1.0"
edition = "2021"
[dependencies]
domain = { workspace = true }
adapter-common = { workspace = true }
async-trait = { workspace = true }
sqlx = { workspace = true }
uuid = { workspace = true }
[dev-dependencies]
tokio = { workspace = true }

View File

@@ -1,15 +0,0 @@
[package]
name = "sqlite-social"
version = "0.1.0"
edition.workspace = true
[dependencies]
sqlx = { workspace = true }
adapter-common = { workspace = true }
domain = { workspace = true }
uuid = { workspace = true }
chrono = { workspace = true }
async-trait = { workspace = true }
[dev-dependencies]
tokio = { workspace = true }

View File

@@ -4,11 +4,10 @@ version = "0.1.0"
edition.workspace = true edition.workspace = true
[dependencies] [dependencies]
sqlx = { workspace = true, features = ["macros"] } sqlx = { workspace = true, features = ["macros", "chrono"] }
adapter-common = { workspace = true }
domain = { workspace = true } domain = { workspace = true }
sqlite-social = { workspace = true } event-payload = { workspace = true }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true } serde_json = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
@@ -22,5 +21,4 @@ bytes = { workspace = true }
async-stream = { workspace = true } async-stream = { workspace = true }
[dev-dependencies] [dev-dependencies]
sqlite-event-queue = { workspace = true }
tempfile = { workspace = true } tempfile = { workspace = true }

View File

@@ -27,13 +27,13 @@ impl SqliteDiaryRepository {
None => sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM reviews") None => sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM reviews")
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error), .map_err(crate::shared::map_sqlx_error),
Some(id) => { Some(id) => {
sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM reviews WHERE movie_id = ?") sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM reviews WHERE movie_id = ?")
.bind(id) .bind(id)
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
} }
} }
@@ -64,7 +64,7 @@ impl SqliteDiaryRepository {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
async fn fetch_movie_diary_rows( async fn fetch_movie_diary_rows(
@@ -96,7 +96,7 @@ impl SqliteDiaryRepository {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
async fn count_user_diary_entries( async fn count_user_diary_entries(
@@ -127,7 +127,7 @@ impl SqliteDiaryRepository {
} }
q.fetch_one(&self.pool) q.fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
async fn fetch_user_diary_rows( async fn fetch_user_diary_rows(
@@ -173,7 +173,7 @@ impl SqliteDiaryRepository {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
} }
@@ -340,7 +340,7 @@ impl DiaryQuery for SqliteDiaryRepository {
let total = count_q let total = count_q
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let rows_q = bind_filter_params!(sqlx::query_as::<_, FeedRow>(&select_sql)); let rows_q = bind_filter_params!(sqlx::query_as::<_, FeedRow>(&select_sql));
let rows = rows_q let rows = rows_q
@@ -348,7 +348,7 @@ impl DiaryQuery for SqliteDiaryRepository {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let items = rows let items = rows
.into_iter() .into_iter()
@@ -373,7 +373,7 @@ impl DiaryQuery for SqliteDiaryRepository {
.bind(&id_str) .bind(&id_str)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.ok_or_else(|| DomainError::NotFound(format!("Movie {}", id_str)))? .ok_or_else(|| DomainError::NotFound(format!("Movie {}", id_str)))?
.into_domain()?; .into_domain()?;
@@ -384,7 +384,7 @@ impl DiaryQuery for SqliteDiaryRepository {
.bind(&id_str) .bind(&id_str)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(ReviewRow::into_domain) .map(ReviewRow::into_domain)
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
@@ -405,7 +405,7 @@ impl DiaryQuery for SqliteDiaryRepository {
.bind(&uid) .bind(&uid)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.into_iter().map(DiaryRow::into_domain).collect() rows.into_iter().map(DiaryRow::into_domain).collect()
} }
@@ -430,7 +430,7 @@ impl DiaryQuery for SqliteDiaryRepository {
while let Some(row) = futures::StreamExt::next(&mut rows).await { while let Some(row) = futures::StreamExt::next(&mut rows).await {
yield match row { yield match row {
Ok(r) => r.into_domain(), Ok(r) => r.into_domain(),
Err(e) => Err(adapter_common::map_sqlx_error(e)), Err(e) => Err(crate::shared::map_sqlx_error(e)),
}; };
} }
}) })
@@ -453,7 +453,7 @@ impl DiaryQuery for SqliteDiaryRepository {
.bind(id_str) .bind(id_str)
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
.map(MovieStatsRow::into_domain) .map(MovieStatsRow::into_domain)
} }
@@ -471,7 +471,7 @@ impl DiaryQuery for SqliteDiaryRepository {
.bind(&id_str) .bind(&id_str)
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let rows = sqlx::query_as::<_, FeedRow>( let rows = sqlx::query_as::<_, FeedRow>(
"SELECT m.id, m.external_metadata_id, m.title, m.release_year, m.director, m.poster_path, "SELECT m.id, m.external_metadata_id, m.title, m.release_year, m.director, m.poster_path,
@@ -492,7 +492,7 @@ impl DiaryQuery for SqliteDiaryRepository {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let items = rows let items = rows
.into_iter() .into_iter()
@@ -512,7 +512,7 @@ impl DiaryQuery for SqliteDiaryRepository {
sqlx::query_scalar("SELECT COUNT(*) FROM reviews WHERE remote_actor_url IS NULL") sqlx::query_scalar("SELECT COUNT(*) FROM reviews WHERE remote_actor_url IS NULL")
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(count as u64) Ok(count as u64)
} }
} }

View File

@@ -1,4 +1,3 @@
mod migrations;
mod payload; mod payload;
use std::sync::Arc; use std::sync::Arc;
@@ -49,7 +48,6 @@ pub struct SqliteEventQueue {
impl SqliteEventQueue { impl SqliteEventQueue {
pub async fn create(pool: SqlitePool, config: DbEventQueueConfig) -> anyhow::Result<Self> { pub async fn create(pool: SqlitePool, config: DbEventQueueConfig) -> anyhow::Result<Self> {
migrations::run(&pool).await?;
Ok(Self { Ok(Self {
pool, pool,
config: Arc::new(config), config: Arc::new(config),

View File

@@ -39,7 +39,7 @@ impl GoalCommand for SqliteGoalRepository {
.bind(&created_at) .bind(&created_at)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -53,7 +53,7 @@ impl GoalCommand for SqliteGoalRepository {
.bind(&id) .bind(&id)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
if result.rows_affected() == 0 { if result.rows_affected() == 0 {
return Err(DomainError::NotFound("Goal not found".into())); return Err(DomainError::NotFound("Goal not found".into()));
@@ -70,7 +70,7 @@ impl GoalCommand for SqliteGoalRepository {
.bind(&uid) .bind(&uid)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
if result.rows_affected() == 0 { if result.rows_affected() == 0 {
return Err(DomainError::NotFound("Goal not found".into())); return Err(DomainError::NotFound("Goal not found".into()));
@@ -97,7 +97,7 @@ impl GoalQuery for SqliteGoalRepository {
.bind(y) .bind(y)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
row.map(|r| row_to_goal(&r)).transpose() row.map(|r| row_to_goal(&r)).transpose()
} }
@@ -112,7 +112,7 @@ impl GoalQuery for SqliteGoalRepository {
.bind(&uid) .bind(&uid)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.iter().map(row_to_goal).collect() rows.iter().map(row_to_goal).collect()
} }

View File

@@ -125,7 +125,7 @@ impl ImportProfileRepository for SqliteImportProfileRepository {
.execute(&self.pool) .execute(&self.pool)
.await .await
.map(|_| ()) .map(|_| ())
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
async fn list_for_user(&self, user_id: &UserId) -> Result<Vec<ImportProfile>, DomainError> { async fn list_for_user(&self, user_id: &UserId) -> Result<Vec<ImportProfile>, DomainError> {
@@ -136,7 +136,7 @@ impl ImportProfileRepository for SqliteImportProfileRepository {
.bind(&uid) .bind(&uid)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.iter() rows.iter()
.map(|r| { .map(|r| {
@@ -178,7 +178,7 @@ impl ImportProfileRepository for SqliteImportProfileRepository {
.bind(&uid_str) .bind(&uid_str)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
row.map(|r| { row.map(|r| {
use sqlx::Row; use sqlx::Row;
@@ -210,6 +210,6 @@ impl ImportProfileRepository for SqliteImportProfileRepository {
.execute(&self.pool) .execute(&self.pool)
.await .await
.map(|_| ()) .map(|_| ())
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
} }

View File

@@ -311,7 +311,7 @@ impl ImportSessionRepository for SqliteImportSessionRepository {
.execute(&self.pool) .execute(&self.pool)
.await .await
.map(|_| ()) .map(|_| ())
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
async fn get( async fn get(
@@ -329,7 +329,7 @@ impl ImportSessionRepository for SqliteImportSessionRepository {
.bind(&uid_str) .bind(&uid_str)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
row.map(|r| { row.map(|r| {
use sqlx::Row; use sqlx::Row;
@@ -356,7 +356,7 @@ impl ImportSessionRepository for SqliteImportSessionRepository {
.execute(&self.pool) .execute(&self.pool)
.await .await
.map(|_| ()) .map(|_| ())
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
async fn delete(&self, id: &ImportSessionId) -> Result<(), DomainError> { async fn delete(&self, id: &ImportSessionId) -> Result<(), DomainError> {
@@ -366,14 +366,14 @@ impl ImportSessionRepository for SqliteImportSessionRepository {
.execute(&self.pool) .execute(&self.pool)
.await .await
.map(|_| ()) .map(|_| ())
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
async fn delete_expired(&self) -> Result<u64, DomainError> { async fn delete_expired(&self) -> Result<u64, DomainError> {
let result = sqlx::query("DELETE FROM import_sessions WHERE expires_at < datetime('now')") let result = sqlx::query("DELETE FROM import_sessions WHERE expires_at < datetime('now')")
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(result.rows_affected()) Ok(result.rows_affected())
} }
@@ -386,6 +386,6 @@ impl ImportSessionRepository for SqliteImportSessionRepository {
.execute(&self.pool) .execute(&self.pool)
.await .await
.map(|_| ()) .map(|_| ())
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
} }

View File

@@ -6,7 +6,7 @@ use domain::{
}; };
use sqlx::{Row, SqlitePool}; use sqlx::{Row, SqlitePool};
use adapter_common::{parse_datetime, parse_uuid}; use crate::shared::{parse_datetime, parse_uuid};
/// SQLite read side of Insights (ADR-0010). Deliberately thin: one query for /// SQLite read side of Insights (ADR-0010). Deliberately thin: one query for
/// review basics, one for genres — every threshold and comparison lives in /// review basics, one for genres — every threshold and comparison lives in
@@ -33,7 +33,7 @@ impl InsightsQuery for SqliteInsightsQuery {
.bind(user_id.value().to_string()) .bind(user_id.value().to_string())
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
// Subquery rather than an `IN (?, …)` bind list: a whole diary can // Subquery rather than an `IN (?, …)` bind list: a whole diary can
// exceed SQLite's bound-parameter limit. // exceed SQLite's bound-parameter limit.
@@ -48,16 +48,14 @@ impl InsightsQuery for SqliteInsightsQuery {
.bind(user_id.value().to_string()) .bind(user_id.value().to_string())
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let mut genres_map: HashMap<String, Vec<String>> = HashMap::new(); let mut genres_map: HashMap<String, Vec<String>> = HashMap::new();
for row in genre_rows { for row in genre_rows {
let mid: String = row let mid: String = row
.try_get("movie_id") .try_get("movie_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let name: String = row let name: String = row.try_get("name").map_err(crate::shared::map_sqlx_error)?;
.try_get("name")
.map_err(adapter_common::map_sqlx_error)?;
genres_map.entry(mid).or_default().push(name); genres_map.entry(mid).or_default().push(name);
} }
@@ -65,16 +63,16 @@ impl InsightsQuery for SqliteInsightsQuery {
for row in &rows { for row in &rows {
let movie_id: String = row let movie_id: String = row
.try_get("movie_id") .try_get("movie_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let rating: i64 = row let rating: i64 = row
.try_get("rating") .try_get("rating")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let watched_at: String = row let watched_at: String = row
.try_get("watched_at") .try_get("watched_at")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let watch_medium: Option<String> = row let watch_medium: Option<String> = row
.try_get("watch_medium") .try_get("watch_medium")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
result.push(WatchRow { result.push(WatchRow {
movie_id: parse_uuid(&movie_id)?, movie_id: parse_uuid(&movie_id)?,

View File

@@ -1,6 +1,7 @@
use sqlx::SqlitePool; use sqlx::SqlitePool;
mod diary; mod diary;
mod event_queue;
mod goals; mod goals;
mod image_ref; mod image_ref;
mod import_profile; mod import_profile;
@@ -15,6 +16,9 @@ mod profile;
mod profile_fields; mod profile_fields;
mod refresh_sessions; mod refresh_sessions;
mod review; mod review;
mod search;
mod shared;
mod social;
mod stats; mod stats;
mod user_settings; mod user_settings;
mod users; mod users;
@@ -23,6 +27,7 @@ mod watchlist;
mod wrapup; mod wrapup;
pub use diary::SqliteDiaryRepository; pub use diary::SqliteDiaryRepository;
pub use event_queue::{DbEventQueueConfig, SqliteEventQueue};
pub use image_ref::{SqliteImageRefAdapter, create_image_ref}; pub use image_ref::{SqliteImageRefAdapter, create_image_ref};
pub use import_profile::SqliteImportProfileRepository; pub use import_profile::SqliteImportProfileRepository;
pub use import_session::SqliteImportSessionRepository; pub use import_session::SqliteImportSessionRepository;
@@ -34,13 +39,23 @@ pub use profile::SqliteMovieProfileRepository;
pub use profile_fields::SqliteProfileFieldsRepository; pub use profile_fields::SqliteProfileFieldsRepository;
pub use refresh_sessions::SqliteRefreshSessionAdapter; pub use refresh_sessions::SqliteRefreshSessionAdapter;
pub use review::SqliteReviewRepository; pub use review::SqliteReviewRepository;
pub use sqlite_social::SqliteApContentQuery; pub use search::create_search_adapter;
pub use social::{
SqliteApContentQuery, SqliteRemoteGoalRepository, SqliteSocialRepository,
create_federated_profile_query,
};
pub use stats::SqliteStatsRepository; pub use stats::SqliteStatsRepository;
pub use users::SqliteUserRepository; pub use users::SqliteUserRepository;
pub use watch_event::{SqliteWatchEventRepository, SqliteWebhookTokenRepository}; pub use watch_event::{SqliteWatchEventRepository, SqliteWebhookTokenRepository};
pub use watchlist::SqliteWatchlistRepository; pub use watchlist::SqliteWatchlistRepository;
pub use wrapup::{SqliteWrapUpRepository, SqliteWrapUpStatsQuery}; pub use wrapup::{SqliteWrapUpRepository, SqliteWrapUpStatsQuery};
/// Row helpers shared with the `sqlite-federation` crate (which cannot live
/// here because it depends on `activitypub`/`k-ap`).
pub mod persistence {
pub use crate::shared::datetime_to_str;
}
pub fn create_profile_fields_repo( pub fn create_profile_fields_repo(
pool: sqlx::SqlitePool, pool: sqlx::SqlitePool,
) -> std::sync::Arc<dyn domain::ports::UserProfileFieldsRepository> { ) -> std::sync::Arc<dyn domain::ports::UserProfileFieldsRepository> {
@@ -122,9 +137,7 @@ pub async fn wire(database_url: &str) -> anyhow::Result<SqliteWireOutput> {
goal_query: std::sync::Arc::new(goals::SqliteGoalRepository::new(pool.clone())) as _, goal_query: std::sync::Arc::new(goals::SqliteGoalRepository::new(pool.clone())) as _,
user_settings: std::sync::Arc::clone(&user_settings_repo) as _, user_settings: std::sync::Arc::clone(&user_settings_repo) as _,
federation_settings: user_settings_repo as _, federation_settings: user_settings_repo as _,
remote_goal: std::sync::Arc::new(sqlite_social::SqliteRemoteGoalRepository::new( remote_goal: std::sync::Arc::new(SqliteRemoteGoalRepository::new(pool.clone())) as _,
pool.clone(),
)) as _,
deduplicator: std::sync::Arc::new(SqliteMovieDeduplicator::new(pool)) as _, deduplicator: std::sync::Arc::new(SqliteMovieDeduplicator::new(pool)) as _,
}) })
} }

View File

@@ -1,4 +1,4 @@
use adapter_common::{ use crate::shared::{
movie_row_to_domain, movie_stats_to_domain, movie_summary_to_domain, review_row_to_domain, movie_row_to_domain, movie_stats_to_domain, movie_summary_to_domain, review_row_to_domain,
user_summary_to_domain, watchlist_entry_to_domain, watchlist_with_movie_to_domain, user_summary_to_domain, watchlist_entry_to_domain, watchlist_with_movie_to_domain,
}; };

View File

@@ -50,7 +50,7 @@ impl MovieCommand for SqliteMovieRepository {
.bind(&poster_path) .bind(&poster_path)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -61,7 +61,7 @@ impl MovieCommand for SqliteMovieRepository {
.bind(&id) .bind(&id)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
} }
@@ -80,7 +80,7 @@ impl MovieQuery for SqliteMovieRepository {
.bind(id) .bind(id)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.map(MovieRow::into_domain) .map(MovieRow::into_domain)
.transpose() .transpose()
} }
@@ -94,7 +94,7 @@ impl MovieQuery for SqliteMovieRepository {
.bind(&id) .bind(&id)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.map(MovieRow::into_domain) .map(MovieRow::into_domain)
.transpose() .transpose()
} }
@@ -114,7 +114,7 @@ impl MovieQuery for SqliteMovieRepository {
.bind(y) .bind(y)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(MovieRow::into_domain) .map(MovieRow::into_domain)
.collect() .collect()
@@ -139,7 +139,7 @@ impl MovieQuery for SqliteMovieRepository {
let rows = q let rows = q
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(rows.into_iter().collect()) Ok(rows.into_iter().collect())
} }
@@ -166,7 +166,7 @@ impl MovieQuery for SqliteMovieRepository {
let rows = q let rows = q
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(rows Ok(rows
.into_iter() .into_iter()
.map(|r| { .map(|r| {
@@ -218,7 +218,7 @@ impl MovieQuery for SqliteMovieRepository {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let total: i64 = sqlx::query( let total: i64 = sqlx::query(
"SELECT COUNT(DISTINCT m.id) \ "SELECT COUNT(DISTINCT m.id) \
@@ -236,7 +236,7 @@ impl MovieQuery for SqliteMovieRepository {
.bind(genre) .bind(genre)
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.try_get(0) .try_get(0)
.unwrap_or(0); .unwrap_or(0);
@@ -260,7 +260,7 @@ impl MovieQuery for SqliteMovieRepository {
) )
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(MovieRow::into_domain) .map(MovieRow::into_domain)
.collect() .collect()

View File

@@ -35,7 +35,7 @@ impl MovieDeduplicator for SqliteMovieDeduplicator {
.pool .pool
.begin() .begin()
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query( sqlx::query(
"INSERT INTO movies (id, external_metadata_id, title, release_year, director, poster_path) "INSERT INTO movies (id, external_metadata_id, title, release_year, director, poster_path)
@@ -45,14 +45,14 @@ impl MovieDeduplicator for SqliteMovieDeduplicator {
poster_path = COALESCE(excluded.poster_path, movies.poster_path)", poster_path = COALESCE(excluded.poster_path, movies.poster_path)",
) )
.bind(&new).bind(&ext_id).bind(&title).bind(year).bind(&director).bind(&poster) .bind(&new).bind(&ext_id).bind(&title).bind(year).bind(&director).bind(&poster)
.execute(&mut *tx).await.map_err(adapter_common::map_sqlx_error)?; .execute(&mut *tx).await.map_err(crate::shared::map_sqlx_error)?;
let reviews = sqlx::query("UPDATE reviews SET movie_id = ? WHERE movie_id = ?") let reviews = sqlx::query("UPDATE reviews SET movie_id = ? WHERE movie_id = ?")
.bind(&new) .bind(&new)
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.rows_affected(); .rows_affected();
let watchlist = sqlx::query("UPDATE watchlist_entries SET movie_id = ? WHERE movie_id = ?") let watchlist = sqlx::query("UPDATE watchlist_entries SET movie_id = ? WHERE movie_id = ?")
@@ -60,7 +60,7 @@ impl MovieDeduplicator for SqliteMovieDeduplicator {
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.rows_affected(); .rows_affected();
let watch_events = sqlx::query("UPDATE watch_events SET movie_id = ? WHERE movie_id = ?") let watch_events = sqlx::query("UPDATE watch_events SET movie_id = ? WHERE movie_id = ?")
@@ -68,7 +68,7 @@ impl MovieDeduplicator for SqliteMovieDeduplicator {
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.rows_affected(); .rows_affected();
let profiles = sqlx::query("UPDATE movie_profiles SET movie_id = ? WHERE movie_id = ?") let profiles = sqlx::query("UPDATE movie_profiles SET movie_id = ? WHERE movie_id = ?")
@@ -76,7 +76,7 @@ impl MovieDeduplicator for SqliteMovieDeduplicator {
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.rows_affected(); .rows_affected();
sqlx::query( sqlx::query(
@@ -87,12 +87,12 @@ impl MovieDeduplicator for SqliteMovieDeduplicator {
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query("DELETE FROM movie_genres WHERE movie_id = ?") sqlx::query("DELETE FROM movie_genres WHERE movie_id = ?")
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query( sqlx::query(
"INSERT OR IGNORE INTO movie_keywords (movie_id, tmdb_id, name) "INSERT OR IGNORE INTO movie_keywords (movie_id, tmdb_id, name)
@@ -102,40 +102,40 @@ impl MovieDeduplicator for SqliteMovieDeduplicator {
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query("DELETE FROM movie_keywords WHERE movie_id = ?") sqlx::query("DELETE FROM movie_keywords WHERE movie_id = ?")
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query( sqlx::query(
"INSERT OR IGNORE INTO movie_cast (movie_id, tmdb_person_id, name, character, billing_order, profile_path) "INSERT OR IGNORE INTO movie_cast (movie_id, tmdb_person_id, name, character, billing_order, profile_path)
SELECT ?, tmdb_person_id, name, character, billing_order, profile_path FROM movie_cast WHERE movie_id = ?", SELECT ?, tmdb_person_id, name, character, billing_order, profile_path FROM movie_cast WHERE movie_id = ?",
).bind(&new).bind(&old).execute(&mut *tx).await.map_err(adapter_common::map_sqlx_error)?; ).bind(&new).bind(&old).execute(&mut *tx).await.map_err(crate::shared::map_sqlx_error)?;
sqlx::query("DELETE FROM movie_cast WHERE movie_id = ?") sqlx::query("DELETE FROM movie_cast WHERE movie_id = ?")
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query( sqlx::query(
"INSERT OR IGNORE INTO movie_crew (movie_id, tmdb_person_id, name, job, department, profile_path) "INSERT OR IGNORE INTO movie_crew (movie_id, tmdb_person_id, name, job, department, profile_path)
SELECT ?, tmdb_person_id, name, job, department, profile_path FROM movie_crew WHERE movie_id = ?", SELECT ?, tmdb_person_id, name, job, department, profile_path FROM movie_crew WHERE movie_id = ?",
).bind(&new).bind(&old).execute(&mut *tx).await.map_err(adapter_common::map_sqlx_error)?; ).bind(&new).bind(&old).execute(&mut *tx).await.map_err(crate::shared::map_sqlx_error)?;
sqlx::query("DELETE FROM movie_crew WHERE movie_id = ?") sqlx::query("DELETE FROM movie_crew WHERE movie_id = ?")
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query("DELETE FROM movies WHERE id = ?") sqlx::query("DELETE FROM movies WHERE id = ?")
.bind(&old) .bind(&old)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
tx.commit().await.map_err(adapter_common::map_sqlx_error)?; tx.commit().await.map_err(crate::shared::map_sqlx_error)?;
Ok(reviews + watchlist + watch_events + profiles) Ok(reviews + watchlist + watch_events + profiles)
} }

View File

@@ -52,7 +52,7 @@ impl PersonCommand for SqlitePersonAdapter {
.bind(person.profile_path()) .bind(person.profile_path())
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
} }
Ok(()) Ok(())
} }
@@ -85,7 +85,7 @@ impl PersonCommand for SqlitePersonAdapter {
.bind(batch_size) .bind(batch_size)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let has_more = rows.len() as u32 >= batch_size; let has_more = rows.len() as u32 >= batch_size;
let mut count = 0u64; let mut count = 0u64;
@@ -105,7 +105,7 @@ impl PersonCommand for SqlitePersonAdapter {
.bind(&row.profile_path) .bind(&row.profile_path)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
count += 1; count += 1;
} }
Ok((count, has_more)) Ok((count, has_more))
@@ -133,7 +133,7 @@ impl PersonCommand for SqlitePersonAdapter {
.bind(id.value().to_string()) .bind(id.value().to_string())
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
} }
@@ -147,7 +147,7 @@ impl PersonQuery for SqlitePersonAdapter {
.bind(id.value().to_string()) .bind(id.value().to_string())
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(row.map(PersonRow::into_person)) Ok(row.map(PersonRow::into_person))
} }
@@ -162,7 +162,7 @@ impl PersonQuery for SqlitePersonAdapter {
.bind(id.value()) .bind(id.value())
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(row.map(PersonRow::into_person)) Ok(row.map(PersonRow::into_person))
} }
@@ -178,7 +178,7 @@ impl PersonQuery for SqlitePersonAdapter {
.bind(id.value().to_string()) .bind(id.value().to_string())
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.flatten(); .flatten();
let Some(tmdb_id) = tmdb_id else { let Some(tmdb_id) = tmdb_id else {
@@ -199,7 +199,7 @@ impl PersonQuery for SqlitePersonAdapter {
.bind(tmdb_id) .bind(tmdb_id)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(|r| CastCredit { .map(|r| CastCredit {
movie_id: MovieId::from_uuid(uuid::Uuid::parse_str(&r.id).unwrap_or_default()), movie_id: MovieId::from_uuid(uuid::Uuid::parse_str(&r.id).unwrap_or_default()),
@@ -220,7 +220,7 @@ impl PersonQuery for SqlitePersonAdapter {
.bind(tmdb_id) .bind(tmdb_id)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(|r| CrewCredit { .map(|r| CrewCredit {
movie_id: MovieId::from_uuid(uuid::Uuid::parse_str(&r.id).unwrap_or_default()), movie_id: MovieId::from_uuid(uuid::Uuid::parse_str(&r.id).unwrap_or_default()),
@@ -243,7 +243,7 @@ impl PersonQuery for SqlitePersonAdapter {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(rows.into_iter().map(PersonRow::into_person).collect()) Ok(rows.into_iter().map(PersonRow::into_person).collect())
} }
@@ -261,7 +261,7 @@ impl PersonQuery for SqlitePersonAdapter {
) )
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(rows Ok(rows
.into_iter() .into_iter()

View File

@@ -28,7 +28,7 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.pool .pool
.begin() .begin()
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query( sqlx::query(
r#"INSERT INTO movie_profiles r#"INSERT INTO movie_profiles
@@ -61,13 +61,13 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&enriched_at) .bind(&enriched_at)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query("DELETE FROM movie_genres WHERE movie_id = ?") sqlx::query("DELETE FROM movie_genres WHERE movie_id = ?")
.bind(&movie_id) .bind(&movie_id)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
for g in &p.genres { for g in &p.genres {
sqlx::query( sqlx::query(
"INSERT OR IGNORE INTO movie_genres (movie_id, tmdb_id, name) VALUES (?,?,?)", "INSERT OR IGNORE INTO movie_genres (movie_id, tmdb_id, name) VALUES (?,?,?)",
@@ -77,14 +77,14 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&g.name) .bind(&g.name)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
} }
sqlx::query("DELETE FROM movie_keywords WHERE movie_id = ?") sqlx::query("DELETE FROM movie_keywords WHERE movie_id = ?")
.bind(&movie_id) .bind(&movie_id)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
for k in &p.keywords { for k in &p.keywords {
sqlx::query( sqlx::query(
"INSERT OR IGNORE INTO movie_keywords (movie_id, tmdb_id, name) VALUES (?,?,?)", "INSERT OR IGNORE INTO movie_keywords (movie_id, tmdb_id, name) VALUES (?,?,?)",
@@ -94,14 +94,14 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&k.name) .bind(&k.name)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
} }
sqlx::query("DELETE FROM movie_cast WHERE movie_id = ?") sqlx::query("DELETE FROM movie_cast WHERE movie_id = ?")
.bind(&movie_id) .bind(&movie_id)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
for c in &p.cast { for c in &p.cast {
sqlx::query( sqlx::query(
"INSERT OR IGNORE INTO movie_cast \ "INSERT OR IGNORE INTO movie_cast \
@@ -116,14 +116,14 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&c.profile_path) .bind(&c.profile_path)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
} }
sqlx::query("DELETE FROM movie_crew WHERE movie_id = ?") sqlx::query("DELETE FROM movie_crew WHERE movie_id = ?")
.bind(&movie_id) .bind(&movie_id)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
for cr in &p.crew { for cr in &p.crew {
sqlx::query( sqlx::query(
"INSERT OR IGNORE INTO movie_crew \ "INSERT OR IGNORE INTO movie_crew \
@@ -138,10 +138,10 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&cr.profile_path) .bind(&cr.profile_path)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
} }
tx.commit().await.map_err(adapter_common::map_sqlx_error) tx.commit().await.map_err(crate::shared::map_sqlx_error)
} }
async fn get_by_movie_id(&self, id: &MovieId) -> Result<Option<MovieProfile>, DomainError> { async fn get_by_movie_id(&self, id: &MovieId) -> Result<Option<MovieProfile>, DomainError> {
@@ -156,7 +156,7 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&movie_id) .bind(&movie_id)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let row = match row { let row = match row {
Some(r) => r, Some(r) => r,
@@ -174,7 +174,7 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&movie_id) .bind(&movie_id)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(|r| Genre { .map(|r| Genre {
tmdb_id: r.try_get::<i64, _>("tmdb_id").unwrap_or(0) as u32, tmdb_id: r.try_get::<i64, _>("tmdb_id").unwrap_or(0) as u32,
@@ -186,7 +186,7 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&movie_id) .bind(&movie_id)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(|r| Keyword { .map(|r| Keyword {
tmdb_id: r.try_get::<i64, _>("tmdb_id").unwrap_or(0) as u32, tmdb_id: r.try_get::<i64, _>("tmdb_id").unwrap_or(0) as u32,
@@ -201,7 +201,7 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&movie_id) .bind(&movie_id)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(|r| CastMember { .map(|r| CastMember {
tmdb_person_id: r.try_get::<i64, _>("tmdb_person_id").unwrap_or(0) as u64, tmdb_person_id: r.try_get::<i64, _>("tmdb_person_id").unwrap_or(0) as u64,
@@ -222,7 +222,7 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&movie_id) .bind(&movie_id)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(|r| CrewMember { .map(|r| CrewMember {
tmdb_person_id: r.try_get::<i64, _>("tmdb_person_id").unwrap_or(0) as u64, tmdb_person_id: r.try_get::<i64, _>("tmdb_person_id").unwrap_or(0) as u64,
@@ -284,7 +284,7 @@ impl MovieProfileRepository for SqliteMovieProfileRepository {
.bind(&threshold) .bind(&threshold)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(rows Ok(rows
.into_iter() .into_iter()

View File

@@ -26,7 +26,7 @@ impl UserProfileFieldsRepository for SqliteProfileFieldsRepository {
.bind(&id_str) .bind(&id_str)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(rows Ok(rows
.iter() .iter()
@@ -48,7 +48,7 @@ impl UserProfileFieldsRepository for SqliteProfileFieldsRepository {
.bind(&id_str) .bind(&id_str)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
for (i, field) in fields.into_iter().enumerate() { for (i, field) in fields.into_iter().enumerate() {
let id = uuid::Uuid::new_v4().to_string(); let id = uuid::Uuid::new_v4().to_string();
@@ -63,7 +63,7 @@ impl UserProfileFieldsRepository for SqliteProfileFieldsRepository {
.bind(position) .bind(position)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
} }
Ok(()) Ok(())

View File

@@ -30,7 +30,7 @@ impl RefreshSessionRepository for SqliteRefreshSessionAdapter {
.bind(session.created_at.to_rfc3339()) .bind(session.created_at.to_rfc3339())
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -41,7 +41,7 @@ impl RefreshSessionRepository for SqliteRefreshSessionAdapter {
.bind(token) .bind(token)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
row.map(RefreshSessionRow::into_domain).transpose() row.map(RefreshSessionRow::into_domain).transpose()
} }
@@ -51,7 +51,7 @@ impl RefreshSessionRepository for SqliteRefreshSessionAdapter {
.bind(token) .bind(token)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -60,7 +60,7 @@ impl RefreshSessionRepository for SqliteRefreshSessionAdapter {
.bind(user_id.value().to_string()) .bind(user_id.value().to_string())
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -70,7 +70,7 @@ impl RefreshSessionRepository for SqliteRefreshSessionAdapter {
.bind(&now) .bind(&now)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(result.rows_affected()) Ok(result.rows_affected())
} }
} }

View File

@@ -8,7 +8,7 @@ use domain::{
use sqlx::SqlitePool; use sqlx::SqlitePool;
use crate::models::ReviewRow; use crate::models::ReviewRow;
use adapter_common::datetime_to_str; use crate::shared::datetime_to_str;
pub struct SqliteReviewRepository { pub struct SqliteReviewRepository {
pool: SqlitePool, pool: SqlitePool,
@@ -51,7 +51,7 @@ impl ReviewRepository for SqliteReviewRepository {
.bind(review.spoilers()) .bind(review.spoilers())
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -65,7 +65,7 @@ impl ReviewRepository for SqliteReviewRepository {
.bind(&id) .bind(&id)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.map(ReviewRow::into_domain) .map(ReviewRow::into_domain)
.transpose() .transpose()
} }
@@ -88,7 +88,7 @@ impl ReviewRepository for SqliteReviewRepository {
.bind(&id) .bind(&id)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -99,7 +99,7 @@ impl ReviewRepository for SqliteReviewRepository {
.bind(&id) .bind(&id)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -112,7 +112,7 @@ impl ReviewRepository for SqliteReviewRepository {
.bind(&uid) .bind(&uid)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(ReviewRow::into_domain) .map(ReviewRow::into_domain)
.collect() .collect()

View File

@@ -5,8 +5,8 @@ use domain::{
errors::DomainError, errors::DomainError,
models::PersonId, models::PersonId,
models::{ models::{
collections::Paginated, EntityType, IndexableDocument, MovieSearchHit, PersonSearchHit, EntityType, IndexableDocument, MovieSearchHit, PersonSearchHit, SearchQuery, SearchResults,
SearchQuery, SearchResults, collections::Paginated,
}, },
ports::{SearchCommand, SearchPort}, ports::{SearchCommand, SearchPort},
value_objects::MovieId, value_objects::MovieId,
@@ -82,7 +82,7 @@ impl SearchCommand for SqliteSearchAdapter {
.bind(&movie_id) .bind(&movie_id)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query( sqlx::query(
"INSERT INTO movies_fts(movie_id, title, director, overview, genres, keywords, cast_names, crew_names, release_year, language) "INSERT INTO movies_fts(movie_id, title, director, overview, genres, keywords, cast_names, crew_names, release_year, language)
@@ -100,7 +100,7 @@ impl SearchCommand for SqliteSearchAdapter {
.bind(&language) .bind(&language)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -114,7 +114,7 @@ impl SearchCommand for SqliteSearchAdapter {
.bind(&person_id) .bind(&person_id)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
sqlx::query( sqlx::query(
"INSERT INTO people_fts(person_id, name, known_for_department) VALUES (?, ?, ?)", "INSERT INTO people_fts(person_id, name, known_for_department) VALUES (?, ?, ?)",
@@ -124,7 +124,7 @@ impl SearchCommand for SqliteSearchAdapter {
.bind(person.known_for_department()) .bind(person.known_for_department())
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -140,7 +140,7 @@ impl SearchCommand for SqliteSearchAdapter {
.bind(id) .bind(id)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
} }
EntityType::Person => { EntityType::Person => {
sqlx::query( sqlx::query(
@@ -149,7 +149,7 @@ impl SearchCommand for SqliteSearchAdapter {
.bind(id) .bind(id)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
} }
} }
Ok(()) Ok(())
@@ -201,7 +201,7 @@ impl SqliteSearchAdapter {
.bind(query.filters.year.map(|y| y as i64)) .bind(query.filters.year.map(|y| y as i64))
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
count as u64 count as u64
} else { } else {
let count: i64 = sqlx::query_scalar( let count: i64 = sqlx::query_scalar(
@@ -217,7 +217,7 @@ impl SqliteSearchAdapter {
.bind(query.filters.year.map(|y| y as i64)) .bind(query.filters.year.map(|y| y as i64))
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
count as u64 count as u64
}; };
@@ -245,7 +245,7 @@ impl SqliteSearchAdapter {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
} else { } else {
sqlx::query_as::<_, Row>( sqlx::query_as::<_, Row>(
"SELECT m.id, m.title, m.release_year, m.director, m.poster_path, "SELECT m.id, m.title, m.release_year, m.director, m.poster_path,
@@ -266,7 +266,7 @@ impl SqliteSearchAdapter {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
}; };
let items = rows let items = rows
.into_iter() .into_iter()
@@ -317,7 +317,7 @@ impl SqliteSearchAdapter {
.bind(&fts_query) .bind(&fts_query)
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
count as u64 count as u64
}; };
@@ -342,7 +342,7 @@ impl SqliteSearchAdapter {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let mut items = Vec::with_capacity(rows.len()); let mut items = Vec::with_capacity(rows.len());
for row in rows { for row in rows {
@@ -351,7 +351,7 @@ impl SqliteSearchAdapter {
.bind(&row.person_id) .bind(&row.person_id)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.flatten(); .flatten();
let known_for_titles = if let Some(tid) = tmdb_id { let known_for_titles = if let Some(tid) = tmdb_id {
@@ -391,5 +391,4 @@ impl SqliteSearchAdapter {
} }
#[cfg(test)] #[cfg(test)]
#[path = "tests/lib.rs"]
mod tests; mod tests;

View File

@@ -1,7 +1,7 @@
use super::create_search_adapter; use super::create_search_adapter;
use domain::{ use domain::{
models::{ models::{
collections::PageParams, EntityType, IndexableDocument, Movie, SearchFilters, SearchQuery, EntityType, IndexableDocument, Movie, SearchFilters, SearchQuery, collections::PageParams,
}, },
value_objects::{MovieId, MovieTitle, ReleaseYear}, value_objects::{MovieId, MovieTitle, ReleaseYear},
}; };

View File

@@ -10,17 +10,17 @@ use domain::{
}, },
}; };
pub fn map_sqlx_error(e: sqlx::Error) -> DomainError { pub(crate) fn map_sqlx_error(e: sqlx::Error) -> DomainError {
tracing::error!("Database error: {:?}", e); tracing::error!("Database error: {:?}", e);
DomainError::InfrastructureError("Database operation failed".into()) DomainError::InfrastructureError("Database operation failed".into())
} }
pub fn parse_uuid(s: &str) -> Result<uuid::Uuid, DomainError> { pub(crate) fn parse_uuid(s: &str) -> Result<uuid::Uuid, DomainError> {
uuid::Uuid::parse_str(s) uuid::Uuid::parse_str(s)
.map_err(|e| DomainError::InfrastructureError(format!("Invalid UUID '{}': {}", s, e))) .map_err(|e| DomainError::InfrastructureError(format!("Invalid UUID '{}': {}", s, e)))
} }
pub fn parse_datetime(s: &str) -> Result<chrono::NaiveDateTime, DomainError> { pub(crate) fn parse_datetime(s: &str) -> Result<chrono::NaiveDateTime, DomainError> {
chrono::NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") chrono::NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S")
.map_err(|e| DomainError::InfrastructureError(format!("Invalid datetime '{}': {}", s, e))) .map_err(|e| DomainError::InfrastructureError(format!("Invalid datetime '{}': {}", s, e)))
} }
@@ -29,7 +29,7 @@ pub fn datetime_to_str(dt: &chrono::NaiveDateTime) -> String {
dt.format("%Y-%m-%d %H:%M:%S").to_string() dt.format("%Y-%m-%d %H:%M:%S").to_string()
} }
pub fn format_year_month(ym: &str) -> String { pub(crate) fn format_year_month(ym: &str) -> String {
let parts: Vec<&str> = ym.splitn(2, '-').collect(); let parts: Vec<&str> = ym.splitn(2, '-').collect();
if parts.len() != 2 { if parts.len() != 2 {
return ym.to_string(); return ym.to_string();
@@ -53,7 +53,7 @@ pub fn format_year_month(ym: &str) -> String {
format!("{} '{}", month, year) format!("{} '{}", month, year)
} }
pub fn movie_row_to_domain( pub(crate) fn movie_row_to_domain(
id: String, id: String,
external_metadata_id: Option<String>, external_metadata_id: Option<String>,
title: String, title: String,
@@ -79,7 +79,7 @@ pub fn movie_row_to_domain(
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn review_row_to_domain( pub(crate) fn review_row_to_domain(
id: String, id: String,
movie_id: String, movie_id: String,
user_id: String, user_id: String,
@@ -117,7 +117,7 @@ pub fn review_row_to_domain(
})) }))
} }
pub fn movie_summary_to_domain( pub(crate) fn movie_summary_to_domain(
movie: Movie, movie: Movie,
genres: Vec<String>, genres: Vec<String>,
runtime_minutes: Option<i64>, runtime_minutes: Option<i64>,
@@ -135,7 +135,7 @@ pub fn movie_summary_to_domain(
} }
} }
pub fn movie_stats_to_domain( pub(crate) fn movie_stats_to_domain(
total_count: i64, total_count: i64,
avg_rating: Option<f64>, avg_rating: Option<f64>,
federated_count: i64, federated_count: i64,
@@ -156,7 +156,7 @@ pub fn movie_stats_to_domain(
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn user_summary_to_domain( pub(crate) fn user_summary_to_domain(
id: String, id: String,
email: String, email: String,
username: String, username: String,
@@ -176,7 +176,7 @@ pub fn user_summary_to_domain(
)) ))
} }
pub fn watchlist_entry_to_domain( pub(crate) fn watchlist_entry_to_domain(
id: String, id: String,
user_id: String, user_id: String,
movie_id: String, movie_id: String,
@@ -190,6 +190,9 @@ pub fn watchlist_entry_to_domain(
}) })
} }
pub fn watchlist_with_movie_to_domain(entry: WatchlistEntry, movie: Movie) -> WatchlistWithMovie { pub(crate) fn watchlist_with_movie_to_domain(
entry: WatchlistEntry,
movie: Movie,
) -> WatchlistWithMovie {
WatchlistWithMovie { entry, movie } WatchlistWithMovie { entry, movie }
} }

View File

@@ -25,7 +25,7 @@ impl SqliteApContentQuery {
// ── Local row types ────────────────────────────────────────────────────────── // ── Local row types ──────────────────────────────────────────────────────────
use adapter_common::{parse_datetime, parse_uuid}; use crate::shared::{parse_datetime, parse_uuid};
#[derive(sqlx::FromRow)] #[derive(sqlx::FromRow)]
struct MovieRow { struct MovieRow {
@@ -205,7 +205,7 @@ impl LocalApContentQuery for SqliteApContentQuery {
.bind(&uid) .bind(&uid)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.into_iter().map(WatchlistRow::into_domain).collect() rows.into_iter().map(WatchlistRow::into_domain).collect()
} }
@@ -225,7 +225,7 @@ impl LocalApContentQuery for SqliteApContentQuery {
.bind(&mid) .bind(&mid)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.into_iter().map(DiaryRow::into_domain).collect() rows.into_iter().map(DiaryRow::into_domain).collect()
} }
@@ -254,7 +254,7 @@ impl LocalApContentQuery for SqliteApContentQuery {
.bind(limit_i64) .bind(limit_i64)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
} else { } else {
sqlx::query_as::<_, DiaryRow>( sqlx::query_as::<_, DiaryRow>(
"SELECT m.id, m.external_metadata_id, m.title, m.release_year, m.director, m.poster_path, "SELECT m.id, m.external_metadata_id, m.title, m.release_year, m.director, m.poster_path,
@@ -269,7 +269,7 @@ impl LocalApContentQuery for SqliteApContentQuery {
.bind(limit_i64) .bind(limit_i64)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
}; };
rows.into_iter().map(DiaryRow::into_domain).collect() rows.into_iter().map(DiaryRow::into_domain).collect()
} }

View File

@@ -7,7 +7,7 @@ use domain::{
use sqlx::Row; use sqlx::Row;
use crate::SqliteSocialRepository; use crate::SqliteSocialRepository;
use adapter_common::datetime_to_str; use crate::shared::datetime_to_str;
fn follow_status_to_str(status: &FollowStatus) -> &'static str { fn follow_status_to_str(status: &FollowStatus) -> &'static str {
match status { match status {

View File

@@ -1,6 +1,6 @@
mod federated_profile; mod federated_profile;
mod follow_repository; mod follow_repository;
mod social; mod local_social;
mod watchlist; mod watchlist;
pub mod ap_content; pub mod ap_content;

View File

@@ -31,7 +31,7 @@ impl RemoteGoalRepository for SqliteRemoteGoalRepository {
.bind(&received) .bind(&received)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -48,7 +48,7 @@ impl RemoteGoalRepository for SqliteRemoteGoalRepository {
.bind(ap_id) .bind(ap_id)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -59,7 +59,7 @@ impl RemoteGoalRepository for SqliteRemoteGoalRepository {
.bind(actor_url) .bind(actor_url)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -69,7 +69,7 @@ impl RemoteGoalRepository for SqliteRemoteGoalRepository {
.bind(actor_url) .bind(actor_url)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -82,7 +82,7 @@ impl RemoteGoalRepository for SqliteRemoteGoalRepository {
.bind(actor_url) .bind(actor_url)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.iter() rows.iter()
.map(|r| { .map(|r| {

View File

@@ -32,7 +32,7 @@ impl SqliteStatsRepository {
.bind(user_id) .bind(user_id)
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error) .map_err(crate::shared::map_sqlx_error)
} }
async fn fetch_user_favorite_director( async fn fetch_user_favorite_director(
@@ -51,7 +51,7 @@ impl SqliteStatsRepository {
.bind(user_id) .bind(user_id)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(row) Ok(row)
} }
@@ -70,7 +70,7 @@ impl SqliteStatsRepository {
.bind(user_id) .bind(user_id)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(row) Ok(row)
} }
} }
@@ -86,7 +86,7 @@ impl StatsRepository for SqliteStatsRepository {
self.fetch_user_most_active_month(&uid) self.fetch_user_most_active_month(&uid)
)?; )?;
let most_active_month = most_active.map(|ym| adapter_common::format_year_month(&ym)); let most_active_month = most_active.map(|ym| crate::shared::format_year_month(&ym));
Ok(UserStats { Ok(UserStats {
total_movies: totals.total, total_movies: totals.total,
@@ -168,14 +168,14 @@ impl StatsRepository for SqliteStatsRepository {
.bind(&uid) .bind(&uid)
.fetch_all(&self.pool) .fetch_all(&self.pool)
) )
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let max_director_count = director_rows.iter().map(|d| d.count).max().unwrap_or(1); let max_director_count = director_rows.iter().map(|d| d.count).max().unwrap_or(1);
let monthly_ratings = rating_rows let monthly_ratings = rating_rows
.into_iter() .into_iter()
.map(|r| MonthlyRating { .map(|r| MonthlyRating {
month_label: adapter_common::format_year_month(&r.month), month_label: crate::shared::format_year_month(&r.month),
year_month: r.month, year_month: r.month,
avg_rating: r.avg_rating, avg_rating: r.avg_rating,
count: r.count, count: r.count,

View File

@@ -28,7 +28,7 @@ impl UserSettingsRepository for SqliteUserSettingsRepository {
.bind(&uid) .bind(&uid)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
match row { match row {
Some(r) => { Some(r) => {
@@ -63,7 +63,7 @@ impl UserSettingsRepository for SqliteUserSettingsRepository {
}) })
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
} }
@@ -79,7 +79,7 @@ impl UserFederationSettingsQuery for SqliteUserSettingsRepository {
.bind(&uid) .bind(&uid)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
match row { match row {
Some(r) => { Some(r) => {

View File

@@ -68,7 +68,7 @@ impl UserRepository for SqliteUserRepository {
.bind(email_str) .bind(email_str)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
row.as_ref() row.as_ref()
.map(|r| Self::row_to_user(r, vec![])) .map(|r| Self::row_to_user(r, vec![]))
@@ -81,7 +81,7 @@ impl UserRepository for SqliteUserRepository {
.bind(username_str) .bind(username_str)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
row.as_ref() row.as_ref()
.map(|r| Self::row_to_user(r, vec![])) .map(|r| Self::row_to_user(r, vec![]))
@@ -121,7 +121,7 @@ impl UserRepository for SqliteUserRepository {
.bind(role) .bind(role)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -132,7 +132,7 @@ impl UserRepository for SqliteUserRepository {
.bind(&id_str) .bind(&id_str)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let Some(r) = row else { return Ok(None) }; let Some(r) = row else { return Ok(None) };
@@ -189,7 +189,7 @@ impl UserRepository for SqliteUserRepository {
) )
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.into_iter() .into_iter()
.map(UserSummaryRow::into_domain) .map(UserSummaryRow::into_domain)
.collect() .collect()

View File

@@ -7,7 +7,7 @@ use domain::{
}; };
use sqlx::{Row, SqlitePool}; use sqlx::{Row, SqlitePool};
use adapter_common::datetime_to_str; use crate::shared::datetime_to_str;
fn parse_uuid(s: &str) -> Result<uuid::Uuid, DomainError> { fn parse_uuid(s: &str) -> Result<uuid::Uuid, DomainError> {
s.parse() s.parse()
@@ -60,7 +60,7 @@ impl WatchEventCommand for SqliteWatchEventRepository {
.bind(&created_at) .bind(&created_at)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -78,7 +78,7 @@ impl WatchEventCommand for SqliteWatchEventRepository {
.bind(&id_str) .bind(&id_str)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -103,7 +103,7 @@ impl WatchEventCommand for SqliteWatchEventRepository {
let result = q let result = q
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(result.rows_affected()) Ok(result.rows_affected())
} }
@@ -117,7 +117,7 @@ impl WatchEventCommand for SqliteWatchEventRepository {
.bind(&before_str) .bind(&before_str)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(result.rows_affected()) Ok(result.rows_affected())
} }
} }
@@ -137,7 +137,7 @@ impl WatchEventQuery for SqliteWatchEventRepository {
.bind(&uid) .bind(&uid)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.iter().map(row_to_watch_event).collect() rows.iter().map(row_to_watch_event).collect()
} }
@@ -153,7 +153,7 @@ impl WatchEventQuery for SqliteWatchEventRepository {
.bind(&id_str) .bind(&id_str)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
row.as_ref().map(row_to_watch_event).transpose() row.as_ref().map(row_to_watch_event).transpose()
} }
@@ -176,7 +176,7 @@ impl WatchEventQuery for SqliteWatchEventRepository {
let rows = q let rows = q
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.iter().map(row_to_watch_event).collect() rows.iter().map(row_to_watch_event).collect()
} }
@@ -198,7 +198,7 @@ impl WatchEventQuery for SqliteWatchEventRepository {
.bind(&after_str) .bind(&after_str)
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.try_get(0) .try_get(0)
.unwrap_or(0); .unwrap_or(0);
@@ -207,34 +207,32 @@ impl WatchEventQuery for SqliteWatchEventRepository {
} }
fn row_to_watch_event(row: &sqlx::sqlite::SqliteRow) -> Result<WatchEvent, DomainError> { fn row_to_watch_event(row: &sqlx::sqlite::SqliteRow) -> Result<WatchEvent, DomainError> {
let id_str: &str = row.try_get("id").map_err(adapter_common::map_sqlx_error)?; let id_str: &str = row.try_get("id").map_err(crate::shared::map_sqlx_error)?;
let user_id_str: &str = row let user_id_str: &str = row
.try_get("user_id") .try_get("user_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let movie_id_str: Option<&str> = row let movie_id_str: Option<&str> = row
.try_get("movie_id") .try_get("movie_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let title: String = row let title: String = row
.try_get("title") .try_get("title")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let year: Option<i64> = row let year: Option<i64> = row.try_get("year").map_err(crate::shared::map_sqlx_error)?;
.try_get("year")
.map_err(adapter_common::map_sqlx_error)?;
let ext_id: Option<String> = row let ext_id: Option<String> = row
.try_get("external_metadata_id") .try_get("external_metadata_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let source_str: String = row let source_str: String = row
.try_get("source") .try_get("source")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let watched_at_str: String = row let watched_at_str: String = row
.try_get("watched_at") .try_get("watched_at")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let status_str: String = row let status_str: String = row
.try_get("status") .try_get("status")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let created_at_str: String = row let created_at_str: String = row
.try_get("created_at") .try_get("created_at")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let source: WatchEventSource = source_str let source: WatchEventSource = source_str
.parse() .parse()
@@ -297,7 +295,7 @@ impl WebhookTokenRepository for SqliteWebhookTokenRepository {
.bind(&last_used) .bind(&last_used)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -310,7 +308,7 @@ impl WebhookTokenRepository for SqliteWebhookTokenRepository {
.bind(hash) .bind(hash)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
row.as_ref().map(row_to_webhook_token).transpose() row.as_ref().map(row_to_webhook_token).transpose()
} }
@@ -325,7 +323,7 @@ impl WebhookTokenRepository for SqliteWebhookTokenRepository {
.bind(&uid) .bind(&uid)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.iter().map(row_to_webhook_token).collect() rows.iter().map(row_to_webhook_token).collect()
} }
@@ -339,7 +337,7 @@ impl WebhookTokenRepository for SqliteWebhookTokenRepository {
.bind(&uid) .bind(&uid)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
if result.rows_affected() == 0 { if result.rows_affected() == 0 {
return Err(DomainError::NotFound(format!("Webhook token {id_str}"))); return Err(DomainError::NotFound(format!("Webhook token {id_str}")));
@@ -356,32 +354,32 @@ impl WebhookTokenRepository for SqliteWebhookTokenRepository {
.bind(&id_str) .bind(&id_str)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
} }
fn row_to_webhook_token(row: &sqlx::sqlite::SqliteRow) -> Result<WebhookToken, DomainError> { fn row_to_webhook_token(row: &sqlx::sqlite::SqliteRow) -> Result<WebhookToken, DomainError> {
let id_str: &str = row.try_get("id").map_err(adapter_common::map_sqlx_error)?; let id_str: &str = row.try_get("id").map_err(crate::shared::map_sqlx_error)?;
let user_id_str: &str = row let user_id_str: &str = row
.try_get("user_id") .try_get("user_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let token_hash: String = row let token_hash: String = row
.try_get("token_hash") .try_get("token_hash")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let provider_str: String = row let provider_str: String = row
.try_get("provider") .try_get("provider")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let label: Option<String> = row let label: Option<String> = row
.try_get("label") .try_get("label")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let created_at_str: String = row let created_at_str: String = row
.try_get("created_at") .try_get("created_at")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let last_used_str: Option<String> = row let last_used_str: Option<String> = row
.try_get("last_used_at") .try_get("last_used_at")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let provider: WatchEventSource = provider_str let provider: WatchEventSource = provider_str
.parse() .parse()

View File

@@ -11,7 +11,7 @@ use domain::{
use sqlx::{Row, SqlitePool}; use sqlx::{Row, SqlitePool};
use crate::models::WatchlistRow; use crate::models::WatchlistRow;
use adapter_common::datetime_to_str; use crate::shared::datetime_to_str;
pub struct SqliteWatchlistRepository { pub struct SqliteWatchlistRepository {
pool: SqlitePool, pool: SqlitePool,
@@ -41,7 +41,7 @@ impl WatchlistRepository for SqliteWatchlistRepository {
.bind(&added_at) .bind(&added_at)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -56,7 +56,7 @@ impl WatchlistRepository for SqliteWatchlistRepository {
.bind(&mid) .bind(&mid)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
if result.rows_affected() == 0 { if result.rows_affected() == 0 {
return Err(DomainError::NotFound(format!( return Err(DomainError::NotFound(format!(
@@ -80,7 +80,7 @@ impl WatchlistRepository for SqliteWatchlistRepository {
.bind(&mid) .bind(&mid)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(result.rows_affected() > 0) Ok(result.rows_affected() > 0)
} }
@@ -108,13 +108,13 @@ impl WatchlistRepository for SqliteWatchlistRepository {
.bind(offset) .bind(offset)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let total: i64 = sqlx::query("SELECT COUNT(*) FROM watchlist_entries WHERE user_id = ?") let total: i64 = sqlx::query("SELECT COUNT(*) FROM watchlist_entries WHERE user_id = ?")
.bind(&uid) .bind(&uid)
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.try_get(0) .try_get(0)
.unwrap_or(0); .unwrap_or(0);
@@ -141,7 +141,7 @@ impl WatchlistRepository for SqliteWatchlistRepository {
.bind(&mid) .bind(&mid)
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)? .map_err(crate::shared::map_sqlx_error)?
.try_get(0) .try_get(0)
.unwrap_or(0); .unwrap_or(0);
Ok(count > 0) Ok(count > 0)

View File

@@ -13,7 +13,7 @@ use domain::{
use sqlx::{Row, SqlitePool}; use sqlx::{Row, SqlitePool};
use uuid::Uuid; use uuid::Uuid;
use adapter_common::{parse_datetime, parse_uuid}; use crate::shared::{parse_datetime, parse_uuid};
fn status_to_str(s: &WrapUpStatus) -> &'static str { fn status_to_str(s: &WrapUpStatus) -> &'static str {
match s { match s {
@@ -82,7 +82,7 @@ impl WrapUpRepository for SqliteWrapUpRepository {
.bind(&completed) .bind(&completed)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -102,7 +102,7 @@ impl WrapUpRepository for SqliteWrapUpRepository {
.bind(&id_str) .bind(&id_str)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -121,7 +121,7 @@ impl WrapUpRepository for SqliteWrapUpRepository {
.bind(&id_str) .bind(&id_str)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -137,7 +137,7 @@ impl WrapUpRepository for SqliteWrapUpRepository {
.bind(&id_str) .bind(&id_str)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
row.as_ref().map(row_to_record).transpose() row.as_ref().map(row_to_record).transpose()
} }
@@ -153,7 +153,7 @@ impl WrapUpRepository for SqliteWrapUpRepository {
.bind(&uid) .bind(&uid)
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.iter().map(row_to_record).collect() rows.iter().map(row_to_record).collect()
} }
@@ -166,7 +166,7 @@ impl WrapUpRepository for SqliteWrapUpRepository {
) )
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
rows.iter().map(row_to_record).collect() rows.iter().map(row_to_record).collect()
} }
@@ -195,7 +195,7 @@ impl WrapUpRepository for SqliteWrapUpRepository {
.bind(&end_str) .bind(&end_str)
.fetch_optional(&self.pool) .fetch_optional(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
row.as_ref().map(row_to_record).transpose() row.as_ref().map(row_to_record).transpose()
} }
@@ -205,7 +205,7 @@ impl WrapUpRepository for SqliteWrapUpRepository {
.bind(id.value().to_string()) .bind(id.value().to_string())
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(()) Ok(())
} }
@@ -219,37 +219,37 @@ impl WrapUpRepository for SqliteWrapUpRepository {
.bind(&before_str) .bind(&before_str)
.execute(&self.pool) .execute(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
Ok(result.rows_affected()) Ok(result.rows_affected())
} }
} }
fn row_to_record(row: &sqlx::sqlite::SqliteRow) -> Result<WrapUpRecord, DomainError> { fn row_to_record(row: &sqlx::sqlite::SqliteRow) -> Result<WrapUpRecord, DomainError> {
let id_str: String = row.try_get("id").map_err(adapter_common::map_sqlx_error)?; let id_str: String = row.try_get("id").map_err(crate::shared::map_sqlx_error)?;
let user_id_str: Option<String> = row let user_id_str: Option<String> = row
.try_get("user_id") .try_get("user_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let start_date_str: String = row let start_date_str: String = row
.try_get("start_date") .try_get("start_date")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let end_date_str: String = row let end_date_str: String = row
.try_get("end_date") .try_get("end_date")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let status_str: String = row let status_str: String = row
.try_get("status") .try_get("status")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let report_json: Option<String> = row let report_json: Option<String> = row
.try_get("report_json") .try_get("report_json")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let error_message: Option<String> = row let error_message: Option<String> = row
.try_get("error_message") .try_get("error_message")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let created_at_str: String = row let created_at_str: String = row
.try_get("created_at") .try_get("created_at")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let completed_at_str: Option<String> = row let completed_at_str: Option<String> = row
.try_get("completed_at") .try_get("completed_at")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let user_id = user_id_str.as_deref().map(parse_uuid).transpose()?; let user_id = user_id_str.as_deref().map(parse_uuid).transpose()?;
@@ -318,7 +318,7 @@ impl WrapUpStatsQuery for SqliteWrapUpStatsQuery {
let rows = q let rows = q
.fetch_all(&self.pool) .fetch_all(&self.pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
if rows.is_empty() { if rows.is_empty() {
return Ok(vec![]); return Ok(vec![]);
@@ -330,7 +330,7 @@ impl WrapUpStatsQuery for SqliteWrapUpStatsQuery {
for row in &rows { for row in &rows {
let mid: String = row let mid: String = row
.try_get("movie_id") .try_get("movie_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
if seen.insert(mid.clone()) { if seen.insert(mid.clone()) {
movie_ids.push(mid); movie_ids.push(mid);
} }
@@ -348,40 +348,40 @@ impl WrapUpStatsQuery for SqliteWrapUpStatsQuery {
for row in &rows { for row in &rows {
let movie_id_str: String = row let movie_id_str: String = row
.try_get("movie_id") .try_get("movie_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let title: String = row let title: String = row
.try_get("title") .try_get("title")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let release_year: i64 = row let release_year: i64 = row
.try_get("release_year") .try_get("release_year")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let director: Option<String> = row let director: Option<String> = row
.try_get("director") .try_get("director")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let poster_path: Option<String> = row let poster_path: Option<String> = row
.try_get("poster_path") .try_get("poster_path")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let rating: i64 = row let rating: i64 = row
.try_get("rating") .try_get("rating")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let watched_at_str: String = row let watched_at_str: String = row
.try_get("watched_at") .try_get("watched_at")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let user_id_str: String = row let user_id_str: String = row
.try_get("user_id") .try_get("user_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let runtime_minutes: Option<i32> = row let runtime_minutes: Option<i32> = row
.try_get("runtime_minutes") .try_get("runtime_minutes")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let budget_usd: Option<i64> = row let budget_usd: Option<i64> = row
.try_get("budget_usd") .try_get("budget_usd")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let original_language: Option<String> = row let original_language: Option<String> = row
.try_get("original_language") .try_get("original_language")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let watch_medium: Option<String> = row let watch_medium: Option<String> = row
.try_get("watch_medium") .try_get("watch_medium")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let genres = genres_map.get(&movie_id_str).cloned().unwrap_or_default(); let genres = genres_map.get(&movie_id_str).cloned().unwrap_or_default();
let keywords = keywords_map.get(&movie_id_str).cloned().unwrap_or_default(); let keywords = keywords_map.get(&movie_id_str).cloned().unwrap_or_default();
@@ -456,16 +456,14 @@ pub(crate) async fn fetch_genres_sqlite(
let rows = q let rows = q
.fetch_all(pool) .fetch_all(pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let mut map: HashMap<String, Vec<String>> = HashMap::new(); let mut map: HashMap<String, Vec<String>> = HashMap::new();
for row in rows { for row in rows {
let mid: String = row let mid: String = row
.try_get("movie_id") .try_get("movie_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let name: String = row let name: String = row.try_get("name").map_err(crate::shared::map_sqlx_error)?;
.try_get("name")
.map_err(adapter_common::map_sqlx_error)?;
map.entry(mid).or_default().push(name); map.entry(mid).or_default().push(name);
} }
Ok(map) Ok(map)
@@ -489,16 +487,14 @@ async fn fetch_keywords_sqlite(
let rows = q let rows = q
.fetch_all(pool) .fetch_all(pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let mut map: HashMap<String, Vec<String>> = HashMap::new(); let mut map: HashMap<String, Vec<String>> = HashMap::new();
for row in rows { for row in rows {
let mid: String = row let mid: String = row
.try_get("movie_id") .try_get("movie_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let name: String = row let name: String = row.try_get("name").map_err(crate::shared::map_sqlx_error)?;
.try_get("name")
.map_err(adapter_common::map_sqlx_error)?;
map.entry(mid).or_default().push(name); map.entry(mid).or_default().push(name);
} }
Ok(map) Ok(map)
@@ -525,25 +521,23 @@ async fn fetch_cast_sqlite(
let rows = q let rows = q
.fetch_all(pool) .fetch_all(pool)
.await .await
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let mut map: HashMap<String, Vec<CastEntry>> = HashMap::new(); let mut map: HashMap<String, Vec<CastEntry>> = HashMap::new();
for row in rows { for row in rows {
let mid: String = row let mid: String = row
.try_get("movie_id") .try_get("movie_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let name: String = row let name: String = row.try_get("name").map_err(crate::shared::map_sqlx_error)?;
.try_get("name")
.map_err(adapter_common::map_sqlx_error)?;
let billing_order: i32 = row let billing_order: i32 = row
.try_get("billing_order") .try_get("billing_order")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let tmdb_person_id: i64 = row let tmdb_person_id: i64 = row
.try_get("tmdb_person_id") .try_get("tmdb_person_id")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
let profile_path: Option<String> = row let profile_path: Option<String> = row
.try_get("profile_path") .try_get("profile_path")
.map_err(adapter_common::map_sqlx_error)?; .map_err(crate::shared::map_sqlx_error)?;
map.entry(mid).or_default().push(CastEntry { map.entry(mid).or_default().push(CastEntry {
name, name,
billing_order: billing_order as u32, billing_order: billing_order as u32,

View File

@@ -10,9 +10,6 @@ const PRE_MERGE_DB: &str = "tests/fixtures/pre_merge.db";
async fn migrate_with_todays_entry_points(pool: &SqlitePool) { async fn migrate_with_todays_entry_points(pool: &SqlitePool) {
sqlite::migrate(pool).await.unwrap(); sqlite::migrate(pool).await.unwrap();
sqlite_event_queue::SqliteEventQueue::create_publisher(pool.clone())
.await
.unwrap();
} }
async fn ledger(pool: &SqlitePool) -> String { async fn ledger(pool: &SqlitePool) -> String {

View File

@@ -22,9 +22,6 @@ anyhow = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
sqlite = { workspace = true } sqlite = { workspace = true }
sqlite-event-queue = { workspace = true }
sqlite-search = { workspace = true }
sqlite-social = { workspace = true }
nats = { workspace = true, optional = true } nats = { workspace = true, optional = true }
activitypub = { workspace = true, optional = true } activitypub = { workspace = true, optional = true }
sqlite-federation = { workspace = true, optional = true } sqlite-federation = { workspace = true, optional = true }

View File

@@ -56,12 +56,12 @@ pub async fn build_database_adapters(
.context("SQLite connection failed")?; .context("SQLite connection failed")?;
let (image_ref_command, image_ref_query) = sqlite::create_image_ref(w.pool.clone()); let (image_ref_command, image_ref_query) = sqlite::create_image_ref(w.pool.clone());
let (pc, pq) = sqlite::create_person_adapter(w.pool.clone()); let (pc, pq) = sqlite::create_person_adapter(w.pool.clone());
let (sc, sp) = sqlite_search::create_search_adapter(w.pool.clone()); let (sc, sp) = sqlite::create_search_adapter(w.pool.clone());
let pf = sqlite::create_profile_fields_repo(w.pool.clone()); let pf = sqlite::create_profile_fields_repo(w.pool.clone());
let we = Arc::new(sqlite::SqliteWatchEventRepository::new(w.pool.clone())); let we = Arc::new(sqlite::SqliteWatchEventRepository::new(w.pool.clone()));
let wt: Arc<dyn WebhookTokenRepository> = let wt: Arc<dyn WebhookTokenRepository> =
Arc::new(sqlite::SqliteWebhookTokenRepository::new(w.pool.clone())); Arc::new(sqlite::SqliteWebhookTokenRepository::new(w.pool.clone()));
let social = Arc::new(sqlite_social::SqliteSocialRepository::new( let social = Arc::new(sqlite::SqliteSocialRepository::new(
w.pool.clone(), w.pool.clone(),
instance.clone(), instance.clone(),
)); ));

View File

@@ -44,9 +44,6 @@ infra-wiring = { workspace = true }
async-trait = { workspace = true } async-trait = { workspace = true }
sqlite = { workspace = true } sqlite = { workspace = true }
sqlite-event-queue = { workspace = true }
sqlite-search = { workspace = true }
sqlite-social = { workspace = true }
# Optional — federation # Optional — federation
activitypub = { workspace = true, optional = true } activitypub = { workspace = true, optional = true }

View File

@@ -211,7 +211,7 @@ async fn wire_dependencies() -> anyhow::Result<(AppState, axum::Router)> {
federated_profile: Some({ federated_profile: Some({
match &db_pool { match &db_pool {
composition::DbPool::Sqlite(pool) => { composition::DbPool::Sqlite(pool) => {
sqlite_social::create_federated_profile_query(pool.clone(), instance.clone()) sqlite::create_federated_profile_query(pool.clone(), instance.clone())
} }
} }
}), }),
@@ -268,7 +268,7 @@ async fn create_event_publisher(
tracing::info!("event bus: DB queue"); tracing::info!("event bus: DB queue");
Ok(match db_pool { Ok(match db_pool {
composition::DbPool::Sqlite(pool) => { composition::DbPool::Sqlite(pool) => {
sqlite_event_queue::SqliteEventQueue::create_publisher(pool.clone()).await? sqlite::SqliteEventQueue::create_publisher(pool.clone()).await?
} }
}) })
} }

View File

@@ -40,8 +40,6 @@ infra-wiring = { workspace = true }
async-trait = { workspace = true } async-trait = { workspace = true }
sqlite = { workspace = true } sqlite = { workspace = true }
sqlite-event-queue = { workspace = true }
sqlite-search = { workspace = true }
# Optional — federation # Optional — federation
activitypub = { workspace = true, optional = true } activitypub = { workspace = true, optional = true }

View File

@@ -14,7 +14,7 @@ pub async fn create(
tracing::info!("event bus: DB queue"); tracing::info!("event bus: DB queue");
match db_pool { match db_pool {
DbPool::Sqlite(pool) => { DbPool::Sqlite(pool) => {
Ok(sqlite_event_queue::SqliteEventQueue::create_channel(pool.clone()).await?) Ok(sqlite::SqliteEventQueue::create_channel(pool.clone()).await?)
} }
} }
} }