Skip to content

Commit

Permalink
Monitor people (#654)
Browse files Browse the repository at this point in the history
* chore(frontend): display stringified stat in html

* chore: remove animation

* Revert "chore: remove animation"

This reverts commit 3ffa4be.

* feat(backend): preference for disabling navigation animations

* feat(frontend): allow updating preference to disable animation

* feat(frontend): respect new preference

* feat(database): migration to rename column

* feat(backend): adapt to new database changes

* feat(database): migration to change metadata reminder to media reminder

* feat(backend): adapt to new database changes

* feat(backend): add more reasons to user_to_person

* refactor(backend): make fn to update user_to_entity more generic

* refactor(backend): make fn to get entities in collection more generic

* fix(backend): use correct filter get user to entity association

* refactor(backend): make fn to add entities to collection more generic

* chore(frontend): adapt to new gql schema

* refactor(frontend): fn to extract the required params

* feat(frontend): move "update person" btn to menu

* feat(backend): allow setting media reminder for people

* feat(database): add check constraint to user_to_entity

* Revert "feat(database): add check constraint to user_to_entity"

This reverts commit 9d9f399.

* refactor(frontend): ext cmpt to add media reminder

* perf(frontend): do not re-run root loader on every run

* fix(frontend): use correct map key

* fix(frontend): make hidden input readonly

* refactor(frontend): move delete reminder to common action

* feat(frontend): component to add hidden location input

* feat(frontend): new common action route

* feat(frontend): use correct key for toast messages

* feat(frontend): remove usage of useless refs

* feat(database): add migration to add new field to user_to_entity table

* fix(database): add correct check for adding column

* feat(backend): respect new `needs_to_be_updated` field

* fix(database): migration should make sure all ute are updated

* fix(backend): update user to entity correctly

* chore(backend): remove useless checks

* chore(frontend): remove old upgrade code

* refactor(graphql): extract fragment for reminders

* feat(backend): get additional user person details

* feat(frontend): allow adding reminders for people

* fix(frontend): change default text for people

* feat(frontend): display reminder for people

* feat(backend): allow toggling monitor on people

* refactor(frontend): action to monitor media

* feat(frontend): display if media is monitored

* chore(backend): add additional for progress update

* fix(frontend): update progress for shows and podcasts correctly

Fixes #659.

* refactor(backend): change name of function to get users to notify

* feat(backend): fn to get users to notify for person

* feat(config,backend): remove useless config param

Signed-off-by Diptesh Choudhuri <[email protected]>

* refactor(backend): change name of enum members

* feat(backend): add new pref for person notification

* feat(frontend): adapt to new gql schema

* feat(backend): add new media state change enum variant

* refactor(backend): extract fn to update metadata and notify user

* perf(backend): do not send a lot of data to update person

* perf(backend): follow clippy lints

* feat(backend): notify users when person updated

* feat(backend): add a development only mutation

* feat(backend): scaffold basic code for cron job

* feat(database): add constraint to `user_to_entity`

* refactor(backend): change description of preference

* feat(backend): generate notifications

* fix(backend): allow tmdb to get all related media for people

* fix(backend): add debug statement for notif

* fix(backend): change notification text for person assoc

* build(backend): bump version

* feat(config): param to disable apalis

* feat(backend): respect new config param

* refactor(backend): code more readable
  • Loading branch information
IgnisDa authored Feb 27, 2024
1 parent 4c1006a commit db2cfaa
Show file tree
Hide file tree
Showing 44 changed files with 1,202 additions and 844 deletions.
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions apps/backend/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ryot"
version = "4.2.10"
version = "4.2.11"
edition = "2021"
repository = "https://github.com/IgnisDa/ryot"
license = "GPL-3.0"
Expand Down Expand Up @@ -60,7 +60,6 @@ scraper = "0.18.1"
sea-orm = { workspace = true }
sea-orm-migration = { workspace = true }
sea-query = "0.30.7"
semver = "1.0.22"
serde = { workspace = true }
serde_json = { workspace = true }
serde_with = { version = "3.6.1", features = ["chrono_0_4"] }
Expand Down
51 changes: 20 additions & 31 deletions apps/backend/src/background.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize};
use strum::Display;

use crate::{
entities::{metadata, person},
exporter::ExporterService,
fitness::resolver::ExerciseService,
importer::{DeployImportJobInput, ImporterService},
Expand Down Expand Up @@ -47,7 +46,14 @@ pub async fn media_jobs(_information: ScheduledJob, ctx: JobContext) -> Result<(
if env::var("DISABLE_UPDATE_WATCHLIST_MEDIA").is_err() {
tracing::trace!("Checking for updates for media in Watchlist");
service
.update_watchlist_media_and_send_notifications()
.update_watchlist_metadata_and_send_notifications()
.await
.unwrap();
}
if env::var("DISABLE_UPDATE_MONITORED_PEOPLE").is_err() {
tracing::trace!("Checking for updates for monitored people");
service
.update_monitored_people_and_send_notifications()
.await
.unwrap();
}
Expand Down Expand Up @@ -138,14 +144,14 @@ pub async fn perform_core_application_job(
Ok(())
}

// The background jobs which can be throttled.
// The background jobs which can be deployed by the application.
#[derive(Debug, Deserialize, Serialize, Display)]
pub enum ApplicationJob {
ImportFromExternalSource(i32, DeployImportJobInput),
ImportFromExternalSource(i32, Box<DeployImportJobInput>),
ReEvaluateUserWorkouts(i32),
UpdateMetadata(metadata::Model),
UpdateMetadata(i32),
UpdateExerciseJob(Exercise),
UpdatePerson(person::Model),
UpdatePerson(i32),
RecalculateCalendarEvents,
AssociateGroupWithMetadata(MetadataLot, MetadataSource, String),
ReviewPosted(ReviewPostedEvent),
Expand Down Expand Up @@ -181,31 +187,14 @@ pub async fn perform_application_job(
.re_evaluate_user_workouts(user_id)
.await
.is_ok(),
ApplicationJob::UpdateMetadata(metadata) => {
let notifications = misc_service.update_metadata(metadata.id).await.unwrap();
if !notifications.is_empty() {
let users_to_notify = misc_service
.users_to_be_notified_for_state_changes()
.await
.unwrap()
.get(&metadata.id)
.cloned()
.unwrap_or_default();
for notification in notifications {
for user_id in users_to_notify.iter() {
misc_service
.send_media_state_changed_notification_for_user(
user_id.to_owned(),
&notification,
)
.await
.ok();
}
}
}
true
}
ApplicationJob::UpdatePerson(person) => misc_service.update_person(person.id).await.is_ok(),
ApplicationJob::UpdateMetadata(metadata_id) => misc_service
.update_metadata_and_notify_users(metadata_id)
.await
.is_ok(),
ApplicationJob::UpdatePerson(person_id) => misc_service
.update_person_and_notify_users(person_id)
.await
.is_ok(),
ApplicationJob::UpdateExerciseJob(exercise) => {
exercise_service.update_exercise(exercise).await.is_ok()
}
Expand Down
14 changes: 4 additions & 10 deletions apps/backend/src/entities/collection_to_entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use async_trait::async_trait;
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};

use crate::utils::{associate_user_with_metadata, associate_user_with_person};
use crate::utils::associate_user_with_entity;

use super::prelude::Collection;

Expand Down Expand Up @@ -106,15 +106,9 @@ impl ActiveModelBehavior for ActiveModel {
.one(db)
.await?
.unwrap();
if let Some(metadata_id) = model.metadata_id {
associate_user_with_metadata(&collection.user_id, &metadata_id, db)
.await
.ok();
} else if let Some(person_id) = model.person_id {
associate_user_with_person(&collection.user_id, &person_id, db)
.await
.ok();
}
associate_user_with_entity(&collection.user_id, model.metadata_id, model.person_id, db)
.await
.ok();
}
Ok(model)
}
Expand Down
14 changes: 4 additions & 10 deletions apps/backend/src/entities/review.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
ImportOrExportItemReviewComment, SeenAnimeExtraInformation, SeenMangaExtraInformation,
SeenPodcastExtraInformation, SeenShowExtraInformation,
},
utils::{associate_user_with_metadata, associate_user_with_person},
utils::associate_user_with_entity,
};

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -118,15 +118,9 @@ impl ActiveModelBehavior for ActiveModel {
C: ConnectionTrait,
{
if insert {
if let Some(metadata_id) = model.metadata_id {
associate_user_with_metadata(&model.user_id, &metadata_id, db)
.await
.ok();
} else if let Some(person_id) = model.person_id {
associate_user_with_person(&model.user_id, &person_id, db)
.await
.ok();
}
associate_user_with_entity(&model.user_id, model.metadata_id, model.person_id, db)
.await
.ok();
}
Ok(model)
}
Expand Down
17 changes: 3 additions & 14 deletions apps/backend/src/entities/seen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@
use async_graphql::SimpleObject;
use async_trait::async_trait;
use chrono::{NaiveDate, Utc};
use chrono::NaiveDate;
use database::SeenState;
use sea_orm::{entity::prelude::*, ActiveValue};
use sea_query::Expr;
use serde::{Deserialize, Serialize};

use crate::{
entities::{prelude::UserToEntity, user_to_entity},
models::media::{
SeenAnimeExtraInformation, SeenMangaExtraInformation, SeenPodcastExtraInformation,
SeenShowExtraInformation,
},
utils::associate_user_with_metadata,
utils::associate_user_with_entity,
};

// When updating a media item's progress, here are the things that should happen:
Expand Down Expand Up @@ -95,19 +93,10 @@ impl ActiveModelBehavior for ActiveModel {
C: ConnectionTrait,
{
if insert {
associate_user_with_metadata(&model.user_id, &model.metadata_id, db)
associate_user_with_entity(&model.user_id, Some(model.metadata_id), None, db)
.await
.ok();
}
UserToEntity::update_many()
.filter(user_to_entity::Column::UserId.eq(model.user_id))
.filter(user_to_entity::Column::MetadataId.eq(model.metadata_id))
.col_expr(
user_to_entity::Column::LastUpdatedOn,
Expr::value(Utc::now()),
)
.exec(db)
.await?;
Ok(model)
}
}
12 changes: 7 additions & 5 deletions apps/backend/src/entities/user_to_entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ pub struct Model {
pub person_id: Option<i32>,
pub metadata_id: Option<i32>,
pub exercise_id: Option<String>,
pub metadata_monitored: Option<bool>,
pub metadata_units_consumed: Option<i32>,
pub metadata_reminder: Option<UserMediaReminder>,
pub metadata_ownership: Option<UserMediaOwnership>,
#[graphql(skip)]
pub media_reason: Option<Vec<UserToMediaReason>>,
pub metadata_units_consumed: Option<i32>,
pub exercise_extra_information: Option<UserToExerciseExtraInformation>,
pub exercise_num_times_interacted: Option<i32>,
#[graphql(skip)]
pub media_reason: Option<Vec<UserToMediaReason>>,
pub media_reminder: Option<UserMediaReminder>,
pub media_monitored: Option<bool>,
#[graphql(skip)]
pub needs_to_be_updated: Option<bool>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
Expand Down
13 changes: 7 additions & 6 deletions apps/backend/src/fitness/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ use crate::{
GithubExerciseAttributes, UserExerciseInput, UserWorkoutInput, UserWorkoutSetRecord,
WorkoutListItem, WorkoutSetRecord,
},
ChangeCollectionToEntityInput, EntityLot, SearchDetails, SearchInput, SearchResults,
StoredUrl,
ChangeCollectionToEntityInput, SearchDetails, SearchInput, SearchResults, StoredUrl,
},
traits::{AuthProvider, GraphqlRepresentation},
utils::{add_entity_to_collection, entity_in_collections, get_ilike_query, partial_user_by_id},
Expand Down Expand Up @@ -371,8 +370,10 @@ impl ExerciseService {
let collections = entity_in_collections(
&self.db,
user_id,
input.exercise_id.clone(),
EntityLot::Exercise,
None,
None,
None,
Some(input.exercise_id.clone()),
)
.await?;
let mut resp = UserExerciseDetails {
Expand Down Expand Up @@ -764,8 +765,8 @@ impl ExerciseService {
user_id,
ChangeCollectionToEntityInput {
collection_name: DefaultCollection::Custom.to_string(),
entity_id: exercise.id.clone(),
entity_lot: EntityLot::Exercise,
exercise_id: Some(exercise.id.clone()),
..Default::default()
},
)
.await?;
Expand Down
21 changes: 14 additions & 7 deletions apps/backend/src/importer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{
CreateOrUpdateCollectionInput, ImportOrExportItemIdentifier, ImportOrExportMediaItem,
PostReviewInput, ProgressUpdateInput,
},
BackgroundJob, ChangeCollectionToEntityInput, EntityLot,
BackgroundJob, ChangeCollectionToEntityInput,
},
traits::AuthProvider,
users::UserReviewScale,
Expand Down Expand Up @@ -235,7 +235,10 @@ impl ImporterService {
.media_service
.perform_application_job
.clone()
.push(ApplicationJob::ImportFromExternalSource(user_id, input))
.push(ApplicationJob::ImportFromExternalSource(
user_id,
Box::new(input),
))
.await
.unwrap();
Ok(job.to_string())
Expand Down Expand Up @@ -267,15 +270,19 @@ impl ImporterService {
Ok(reports)
}

pub async fn start_importing(&self, user_id: i32, input: DeployImportJobInput) -> Result<()> {
pub async fn start_importing(
&self,
user_id: i32,
input: Box<DeployImportJobInput>,
) -> Result<()> {
match input.source {
ImportSource::StrongApp => self.import_exercises(user_id, input).await,
_ => self.import_media(user_id, input).await,
}
}

#[instrument(skip(self, input))]
async fn import_exercises(&self, user_id: i32, input: DeployImportJobInput) -> Result<()> {
async fn import_exercises(&self, user_id: i32, input: Box<DeployImportJobInput>) -> Result<()> {
let db_import_job = self.start_import_job(user_id, input.source).await?;
let import = match input.source {
ImportSource::StrongApp => {
Expand All @@ -302,7 +309,7 @@ impl ImporterService {
}

#[instrument(skip(self, input))]
async fn import_media(&self, user_id: i32, input: DeployImportJobInput) -> Result<()> {
async fn import_media(&self, user_id: i32, input: Box<DeployImportJobInput>) -> Result<()> {
let db_import_job = self.start_import_job(user_id, input.source).await?;
let mut import = match input.source {
ImportSource::MediaTracker => media_tracker::import(input.media_tracker.unwrap())
Expand Down Expand Up @@ -469,8 +476,8 @@ impl ImporterService {
user_id,
ChangeCollectionToEntityInput {
collection_name: col.to_string(),
entity_id: metadata.id.to_string(),
entity_lot: EntityLot::Media,
metadata_id: Some(metadata.id),
..Default::default()
},
)
.await
Expand Down
18 changes: 11 additions & 7 deletions apps/backend/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::{
env,
fs::{self, create_dir_all},
io::{Error as IoError, ErrorKind as IoErrorKind},
path::PathBuf,
str::FromStr,
sync::{Arc, Mutex},
Expand Down Expand Up @@ -32,7 +31,7 @@ use rs_utils::PROJECT_NAME;
use sea_orm::{ConnectOptions, Database, EntityTrait, PaginatorTrait};
use sea_orm_migration::MigratorTrait;
use sqlx::{pool::PoolOptions, SqlitePool};
use tokio::{net::TcpListener, try_join};
use tokio::{join, net::TcpListener};
use tower_http::{
catch_panic::CatchPanicLayer as TowerCatchPanicLayer, cors::CorsLayer as TowerCorsLayer,
trace::TraceLayer as TowerTraceLayer,
Expand Down Expand Up @@ -95,6 +94,7 @@ async fn main() -> Result<()> {
let user_cleanup_every = config.scheduler.user_cleanup_every;
let pull_every = config.integration.pull_every;
let max_file_size = config.server.max_file_size;
let disable_background_jobs = config.server.disable_background_jobs;
fs::write(
&config.server.config_dump_path,
serde_json::to_string_pretty(&config)?,
Expand Down Expand Up @@ -248,7 +248,7 @@ async fn main() -> Result<()> {
let exercise_service_1 = app_services.exercise_service.clone();

let monitor = async {
let mn = Monitor::new()
Monitor::new()
// cron jobs
.register_with_count(1, move |c| {
WorkerBuilder::new(format!("general_user_cleanup-{c}"))
Expand Down Expand Up @@ -313,17 +313,21 @@ async fn main() -> Result<()> {
.build_fn(perform_application_job)
})
.run()
.await;
Ok(mn)
.await
.unwrap();
};

let http = async {
axum::serve(listener, app_routes.into_make_service())
.await
.map_err(|e| IoError::new(IoErrorKind::Interrupted, e))
.unwrap();
};

let _res = try_join!(monitor, http).expect("Could not start services");
if disable_background_jobs {
join!(http);
} else {
join!(monitor, http);
}

Ok(())
}
Expand Down
Loading

0 comments on commit db2cfaa

Please sign in to comment.