116 lines
3.5 KiB
Rust
116 lines
3.5 KiB
Rust
//! A remote review and the enrichment request it triggers commit together.
|
|
|
|
use activitypub::{NewRemoteReview, RemoteReviewRepository};
|
|
use domain::{
|
|
events::DomainEvent,
|
|
models::{PersistedReview, Review, ReviewSource},
|
|
value_objects::{Comment, ExternalMetadataId, MovieId, Rating, ReviewId, UserId},
|
|
};
|
|
use sqlite_federation::SqliteFederationRepository;
|
|
use sqlx::SqlitePool;
|
|
|
|
const ACTOR: &str = "https://remote.example/users/ann";
|
|
const AP_ID: &str = "https://remote.example/reviews/1";
|
|
|
|
async fn migrated_pool() -> SqlitePool {
|
|
let pool = sqlx::sqlite::SqlitePoolOptions::new()
|
|
.max_connections(1)
|
|
.connect("sqlite::memory:")
|
|
.await
|
|
.unwrap();
|
|
sqlite::migrate(&pool).await.unwrap();
|
|
pool
|
|
}
|
|
|
|
async fn count(pool: &SqlitePool, table: &str) -> i64 {
|
|
sqlx::query_scalar(&format!("SELECT COUNT(*) FROM {table}"))
|
|
.fetch_one(pool)
|
|
.await
|
|
.unwrap()
|
|
}
|
|
|
|
fn remote_review(movie_id: &MovieId) -> Review {
|
|
let now = chrono::Utc::now().naive_utc();
|
|
Review::from_persistence(PersistedReview {
|
|
id: ReviewId::generate(),
|
|
movie_id: movie_id.clone(),
|
|
user_id: UserId::generate(),
|
|
rating: Rating::new(4).unwrap(),
|
|
comment: Some(Comment::new("good".into()).unwrap()),
|
|
watched_at: now,
|
|
created_at: now,
|
|
source: ReviewSource::Remote {
|
|
actor_url: ACTOR.into(),
|
|
},
|
|
watch_medium: None,
|
|
spoilers: false,
|
|
})
|
|
}
|
|
|
|
fn enrichment_requested(movie_id: &MovieId) -> DomainEvent {
|
|
DomainEvent::MovieEnrichmentRequested {
|
|
movie_id: movie_id.clone(),
|
|
external_metadata_id: ExternalMetadataId::new("tmdb:603".into()).unwrap(),
|
|
}
|
|
}
|
|
|
|
async fn save(pool: &SqlitePool, review: &Review, events: &[DomainEvent]) -> anyhow::Result<()> {
|
|
SqliteFederationRepository::new(pool.clone())
|
|
.save_remote_review(NewRemoteReview {
|
|
review,
|
|
ap_id: AP_ID,
|
|
movie_title: "The Matrix",
|
|
release_year: 1999,
|
|
external_metadata_id: Some("tmdb:603"),
|
|
poster_url: None,
|
|
events,
|
|
})
|
|
.await
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn saving_a_remote_review_writes_it_and_its_event_in_one_commit() {
|
|
let pool = migrated_pool().await;
|
|
let movie_id = MovieId::generate();
|
|
let review = remote_review(&movie_id);
|
|
|
|
save(&pool, &review, &[enrichment_requested(&movie_id)])
|
|
.await
|
|
.unwrap();
|
|
|
|
assert_eq!(count(&pool, "reviews").await, 1);
|
|
assert_eq!(count(&pool, "movies").await, 1);
|
|
assert_eq!(count(&pool, "event_queue").await, 1);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn a_failing_enqueue_rolls_back_the_remote_review_and_its_movie() {
|
|
let pool = migrated_pool().await;
|
|
sqlx::query(
|
|
"CREATE TRIGGER fail_event_insert BEFORE INSERT ON event_queue \
|
|
BEGIN SELECT RAISE(ABORT, 'enqueue failed'); END",
|
|
)
|
|
.execute(&pool)
|
|
.await
|
|
.unwrap();
|
|
let movie_id = MovieId::generate();
|
|
let review = remote_review(&movie_id);
|
|
|
|
let result = save(&pool, &review, &[enrichment_requested(&movie_id)]).await;
|
|
|
|
assert!(result.is_err());
|
|
assert_eq!(count(&pool, "reviews").await, 0);
|
|
assert_eq!(count(&pool, "movies").await, 0);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn a_remote_review_without_events_enqueues_nothing() {
|
|
let pool = migrated_pool().await;
|
|
let movie_id = MovieId::generate();
|
|
|
|
save(&pool, &remote_review(&movie_id), &[]).await.unwrap();
|
|
|
|
assert_eq!(count(&pool, "reviews").await, 1);
|
|
assert_eq!(count(&pool, "event_queue").await, 0);
|
|
}
|