diff --git a/Cargo.lock b/Cargo.lock index 1ba4efde85..2ef9300153 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -423,17 +423,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "async-lock" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - [[package]] name = "async-oneshot" version = "0.5.9" @@ -874,7 +863,6 @@ dependencies = [ "migrations", "miscellaneous-resolver", "miscellaneous-service", - "moka", "openidconnect", "reqwest 0.12.9", "router-resolver", @@ -1500,24 +1488,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-queue" version = "0.3.11" @@ -2219,16 +2189,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "event-listener-strategy" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" -dependencies = [ - "event-listener", - "pin-project-lite", -] - [[package]] name = "eventsource-stream" version = "0.2.3" @@ -3894,30 +3854,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "moka" -version = "0.12.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f" -dependencies = [ - "async-lock", - "async-trait", - "crossbeam-channel", - "crossbeam-epoch", - "crossbeam-utils", - "event-listener", - "futures-util", - "once_cell", - "parking_lot", - "quanta", - "rustc_version", - "smallvec", - "tagptr", - "thiserror", - "triomphe", - "uuid", -] - [[package]] name = "multer" version = "3.1.0" @@ -4749,21 +4685,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "quanta" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" -dependencies = [ - "crossbeam-utils", - "libc", - "once_cell", - "raw-cpuid", - "wasi", - "web-sys", - "winapi", -] - [[package]] name = "quote" version = "1.0.37" @@ -4861,15 +4782,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "raw-cpuid" -version = "11.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0" -dependencies = [ - "bitflags 2.6.0", -] - [[package]] name = "redis" version = "0.25.4" @@ -6381,8 +6293,6 @@ dependencies = [ "chrono-tz", "config", "file-storage-service", - "media-models", - "moka", "openidconnect", "sea-orm", ] @@ -6498,12 +6408,6 @@ dependencies = [ "libc", ] -[[package]] -name = "tagptr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" - [[package]] name = "tap" version = "1.0.1" @@ -6928,12 +6832,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "triomphe" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" - [[package]] name = "try-lock" version = "0.2.5" diff --git a/Cargo.toml b/Cargo.toml index fb76d04975..17a46b52d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,7 +79,6 @@ itertools = "=0.13.0" futures = "=0.3.31" hashbag = "=0.1.12" markdown = "=1.0.0-alpha.21" -moka = { version = "=0.12.8", features = ["future"] } nanoid = "=0.4.0" openidconnect = "=3.5.0" regex = "=1.11.1" diff --git a/apps/backend/Cargo.toml b/apps/backend/Cargo.toml index 1966b38fe4..660b3ecc40 100644 --- a/apps/backend/Cargo.toml +++ b/apps/backend/Cargo.toml @@ -38,7 +38,6 @@ integration-service = { path = "../../crates/services/integration" } itertools = { workspace = true } logs-wheel = "=0.3.1" media-models = { path = "../../crates/models/media" } -moka = { workspace = true } migrations = { path = "../../crates/migrations" } miscellaneous-resolver = { path = "../../crates/resolvers/miscellaneous" } miscellaneous-service = { path = "../../crates/services/miscellaneous" } diff --git a/apps/backend/src/common.rs b/apps/backend/src/common.rs index 0601cdeac7..f2a5b2a794 100644 --- a/apps/backend/src/common.rs +++ b/apps/backend/src/common.rs @@ -12,7 +12,6 @@ use axum::{ }; use background::{ApplicationJob, CoreApplicationJob}; use cache_service::CacheService; -use chrono::Duration; use collection_resolver::{CollectionMutation, CollectionQuery}; use collection_service::CollectionService; use common_utils::{ryot_log, FRONTEND_OAUTH_ENDPOINT}; @@ -28,7 +27,6 @@ use integration_service::IntegrationService; use itertools::Itertools; use miscellaneous_resolver::{MiscellaneousMutation, MiscellaneousQuery}; use miscellaneous_service::MiscellaneousService; -use moka::future::Cache; use openidconnect::{ core::{CoreClient, CoreProviderMetadata}, reqwest::async_http_client, @@ -48,13 +46,13 @@ use user_service::UserService; /// All the services that are used by the app pub struct AppServices { - pub miscellaneous_service: Arc, + pub app_router: Router, pub importer_service: Arc, pub exporter_service: Arc, pub exercise_service: Arc, - pub integration_service: Arc, pub statistics_service: Arc, - pub app_router: Router, + pub integration_service: Arc, + pub miscellaneous_service: Arc, } #[allow(clippy::too_many_arguments)] @@ -73,9 +71,6 @@ pub async fn create_app_services( config.file_storage.s3_bucket_name.clone(), )); let cache_service = CacheService::new(&db); - let commit_cache = Cache::builder() - .time_to_live(Duration::try_hours(1).unwrap().to_std().unwrap()) - .build(); let supporting_service = Arc::new( SupportingService::new( is_pro, @@ -84,7 +79,6 @@ pub async fn create_app_services( cache_service, config.clone(), oidc_client, - commit_cache, file_storage_service.clone(), perform_application_job, perform_core_application_job, diff --git a/apps/frontend/app/components/common.tsx b/apps/frontend/app/components/common.tsx index 32d0e909a1..9b2536980b 100644 --- a/apps/frontend/app/components/common.tsx +++ b/apps/frontend/app/components/common.tsx @@ -29,24 +29,12 @@ import { rem, } from "@mantine/core"; import { useDebouncedValue, useDidUpdate, useDisclosure } from "@mantine/hooks"; +import { Form, Link, useFetcher, useNavigate } from "@remix-run/react"; import { - Form, - Link, - useFetcher, - useNavigate, - useRevalidator, -} from "@remix-run/react"; -import { - DeployUpdateMetadataGroupJobDocument, - DeployUpdateMetadataJobDocument, - DeployUpdatePersonJobDocument, EntityLot, GridPacking, type MediaLot, type MediaSource, - MetadataDetailsDocument, - MetadataGroupDetailsDocument, - PersonDetailsDocument, type ReviewItem, UserReviewScale, } from "@ryot/generated/graphql/backend/graphql"; @@ -71,7 +59,6 @@ import { IconTrash, IconX, } from "@tabler/icons-react"; -import { useMutation, useQuery } from "@tanstack/react-query"; import Cookies from "js-cookie"; import type { ReactNode, Ref } from "react"; import { useState } from "react"; @@ -82,7 +69,6 @@ import { withQuery } from "ufo"; import { PRO_REQUIRED_MESSAGE, ThreePointSmileyRating, - clientGqlService, convertDecimalToThreePointSmiley, dayjsLib, getSurroundingElements, @@ -132,81 +118,16 @@ export const ApplicationGrid = (props: { }; export const MediaDetailsLayout = (props: { - children: Array; images: Array; - entityDetails: { id: string; lot: EntityLot; isPartial?: boolean | null }; + children: Array; externalLink?: { source: MediaSource; lot?: MediaLot; href?: string | null; }; }) => { - const revalidator = useRevalidator(); const [activeImageId, setActiveImageId] = useState(0); const fallbackImageUrl = useFallbackImageUrl(); - const [mutationHasRunOnce, setMutationHasRunOnce] = useState(false); - const entityIsPartial = useQuery({ - queryKey: ["MediaDetailsLayout", "entityIsPartial", props.entityDetails], - queryFn: async () => { - const isPartial = await match(props.entityDetails.lot) - .with(EntityLot.Metadata, () => - clientGqlService - .request(MetadataDetailsDocument, { - metadataId: props.entityDetails.id, - }) - .then((data) => data.metadataDetails.isPartial), - ) - .with(EntityLot.Person, () => - clientGqlService - .request(PersonDetailsDocument, { - personId: props.entityDetails.id, - }) - .then((data) => data.personDetails.details.isPartial), - ) - .with(EntityLot.MetadataGroup, () => - clientGqlService - .request(MetadataGroupDetailsDocument, { - metadataGroupId: props.entityDetails.id, - }) - .then((data) => data.metadataGroupDetails.details.isPartial), - ) - .run(); - return isPartial; - }, - refetchInterval: (query) => - query.state.data - ? dayjsLib.duration(2, "seconds").asMilliseconds() - : false, - enabled: props.entityDetails.isPartial === true, - }); - const commitEntity = useMutation({ - mutationFn: async () => - match(props.entityDetails.lot) - .with(EntityLot.Metadata, () => - clientGqlService.request(DeployUpdateMetadataJobDocument, { - metadataId: props.entityDetails.id, - }), - ) - .with(EntityLot.MetadataGroup, () => - clientGqlService.request(DeployUpdateMetadataGroupJobDocument, { - metadataGroupId: props.entityDetails.id, - }), - ) - .with(EntityLot.Person, () => - clientGqlService.request(DeployUpdatePersonJobDocument, { - personId: props.entityDetails.id, - }), - ) - .run(), - onSuccess: () => { - setMutationHasRunOnce(true); - setTimeout(() => revalidator.revalidate(), 5000); - }, - }); - - useDidUpdate(() => { - if (entityIsPartial.data && !mutationHasRunOnce) commitEntity.mutate(); - }, [entityIsPartial]); return ( diff --git a/apps/frontend/app/lib/generals.ts b/apps/frontend/app/lib/generals.ts index b9ee300f3f..ade37f551a 100644 --- a/apps/frontend/app/lib/generals.ts +++ b/apps/frontend/app/lib/generals.ts @@ -43,11 +43,11 @@ declare global { } } -dayjs.extend(relativeTime); -dayjs.extend(duration); -dayjs.extend(localizedFormat); dayjs.extend(utc); +dayjs.extend(duration); dayjs.extend(timezone); +dayjs.extend(relativeTime); +dayjs.extend(localizedFormat); export { dayjs as dayjsLib }; diff --git a/apps/frontend/app/routes/_dashboard.calendar.tsx b/apps/frontend/app/routes/_dashboard.calendar.tsx index 14d45e25e0..b8111315c8 100644 --- a/apps/frontend/app/routes/_dashboard.calendar.tsx +++ b/apps/frontend/app/routes/_dashboard.calendar.tsx @@ -1,27 +1,29 @@ import { ActionIcon, - Anchor, Box, Button, - Card, Container, Group, Stack, Text, Title, - Tooltip, } from "@mantine/core"; import type { LoaderFunctionArgs, MetaArgs } from "@remix-run/node"; -import { Link, useLoaderData } from "@remix-run/react"; +import { useLoaderData } from "@remix-run/react"; import { + type CalendarEventPartFragment, + MediaLot, UserCalendarEventsDocument, type UserCalendarEventsQuery, } from "@ryot/generated/graphql/backend/graphql"; -import { isNumber, snakeCase, startCase, sum, truncate } from "@ryot/ts-utils"; +import { sum } from "@ryot/ts-utils"; import { IconChevronLeft, IconChevronRight } from "@tabler/icons-react"; -import { $path } from "remix-routes"; +import { Fragment } from "react/jsx-runtime"; +import { match } from "ts-pattern"; import { z } from "zod"; import { zx } from "zodix"; +import { ApplicationGrid } from "~/components/common"; +import { MetadataDisplayItem } from "~/components/media"; import { dayjsLib } from "~/lib/generals"; import { useAppSearchParam } from "~/lib/hooks"; import { @@ -46,7 +48,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { input: { month: date.month() + 1, year: date.year() }, }), ]); - return { query, userCalendarEvents, cookieName }; + return { userCalendarEvents, cookieName, query }; }; export const meta = (_args: MetaArgs) => { @@ -59,7 +61,7 @@ export default function Page() { const date = dayjsLib(loaderData.query.date); return ( - + @@ -88,7 +90,7 @@ export default function Page() { </Button.Group> </Group> {loaderData.userCalendarEvents.length > 0 ? ( - <Box> + <Stack gap={4}> <Box> <Text display="inline" fw="bold"> {sum(loaderData.userCalendarEvents.map((e) => e.events.length))} @@ -96,9 +98,9 @@ export default function Page() { items found </Box> {loaderData.userCalendarEvents.map((ce) => ( - <CalendarEvent day={ce} key={ce.date} /> + <CalendarEvent key={ce.date} data={ce} /> ))} - </Box> + </Stack> ) : ( <Text fs="italic">No events in this time period</Text> )} @@ -108,64 +110,52 @@ export default function Page() { } const CalendarEvent = (props: { - day: UserCalendarEventsQuery["userCalendarEvents"][number]; + data: UserCalendarEventsQuery["userCalendarEvents"][number]; }) => { - const date = dayjsLib(props.day.date); + const date = dayjsLib(props.data.date); return ( - <Card - data-calendar-date={props.day.date} - withBorder - radius="sm" - padding="xs" - mt="sm" - > - <Card.Section withBorder p="sm"> - <Group justify="space-between"> - <Text>{date.format("D MMMM")}</Text> - <Text>{date.format("dddd")}</Text> - </Group> - </Card.Section> - {props.day.events.map((evt) => ( - <Group - key={evt.calendarEventId} - data-calendar-event-id={evt.calendarEventId} - justify="space-between" - align="end" - > - <Text mt="sm" size="sm"> - <Tooltip label={evt.metadataTitle} disabled={!evt.episodeName}> - <Anchor - component={Link} - to={$path("/media/item/:id", { - id: evt.metadataId, - })} - > - {truncate(evt.episodeName ?? evt.metadataTitle, { length: 40 })} - </Anchor> - </Tooltip>{" "} - {isNumber(evt.showExtraInformation?.season) ? ( - <Text span c="dimmed" size="sm"> - (S{evt.showExtraInformation.season}-E - {evt.showExtraInformation.episode}) - </Text> - ) : null} - {isNumber(evt.podcastExtraInformation?.episode) ? ( - <Text span c="dimmed" size="sm"> - (EP-{evt.podcastExtraInformation.episode}) - </Text> - ) : null} - {isNumber(evt.animeExtraInformation?.episode) ? ( - <Text span c="dimmed" size="sm"> - (EP-{evt.animeExtraInformation.episode}) - </Text> - ) : null} + <Fragment> + <Group data-calendar-date={props.data.date}> + <Text fz={{ base: "h1" }} fw="bold"> + {date.format("D")} + </Text> + <Stack gap={2}> + <Text size="sm" style={{ lineHeight: "0.9" }}> + {date.format("MMMM")} </Text> - <Text size="sm" c="dimmed"> - {startCase(snakeCase(evt.metadataLot))} + <Text size="sm" fw="bold"> + {date.format("dddd")} </Text> - </Group> - ))} - </Card> + </Stack> + </Group> + <ApplicationGrid> + {props.data.events.map((evt) => ( + <DisplayCalendarEvent key={evt.calendarEventId} calEvent={evt} /> + ))} + </ApplicationGrid> + </Fragment> + ); +}; + +const DisplayCalendarEvent = ({ + calEvent, +}: { calEvent: CalendarEventPartFragment }) => { + return ( + <MetadataDisplayItem + metadataId={calEvent.metadataId} + altName={calEvent.episodeName || calEvent.metadataTitle} + rightLabel={`${match(calEvent.metadataLot) + .with( + MediaLot.Show, + () => + `S${calEvent.showExtraInformation?.season}-E${calEvent.showExtraInformation?.episode}`, + ) + .with( + MediaLot.Podcast, + () => `EP-${calEvent.podcastExtraInformation?.episode}`, + ) + .otherwise(() => "")}`} + /> ); }; diff --git a/apps/frontend/app/routes/_dashboard.media.groups.item.$id._index.tsx b/apps/frontend/app/routes/_dashboard.media.groups.item.$id._index.tsx index f3f1b146a2..72b5468c85 100644 --- a/apps/frontend/app/routes/_dashboard.media.groups.item.$id._index.tsx +++ b/apps/frontend/app/routes/_dashboard.media.groups.item.$id._index.tsx @@ -13,6 +13,7 @@ import { import type { LoaderFunctionArgs, MetaArgs } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { + DeployUpdateMetadataGroupJobDocument, EntityLot, MetadataGroupDetailsDocument, UserMetadataGroupDetailsDocument, @@ -58,6 +59,10 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => { { metadataGroupId }, ), ]); + if (metadataGroupDetails.details.isPartial) + await serverGqlService.request(DeployUpdateMetadataGroupJobDocument, { + metadataGroupId, + }); return { query, metadataGroupId, @@ -80,11 +85,6 @@ export default function Page() { <Container> <MediaDetailsLayout images={loaderData.metadataGroupDetails.details.displayImages} - entityDetails={{ - id: loaderData.metadataGroupId, - lot: EntityLot.MetadataGroup, - isPartial: loaderData.metadataGroupDetails.details.isPartial, - }} externalLink={{ source: loaderData.metadataGroupDetails.details.source, lot: loaderData.metadataGroupDetails.details.lot, diff --git a/apps/frontend/app/routes/_dashboard.media.item.$id._index.tsx b/apps/frontend/app/routes/_dashboard.media.item.$id._index.tsx index 3d926e60d9..3a4dadbe00 100644 --- a/apps/frontend/app/routes/_dashboard.media.item.$id._index.tsx +++ b/apps/frontend/app/routes/_dashboard.media.item.$id._index.tsx @@ -40,6 +40,7 @@ import type { import { Form, Link, useLoaderData } from "@remix-run/react"; import { DeleteSeenItemDocument, + DeployUpdateMetadataJobDocument, DisassociateMetadataDocument, EntityLot, MediaLot, @@ -157,6 +158,10 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => { { metadataId }, ), ]); + if (metadataDetails.isPartial) + await serverGqlService.request(DeployUpdateMetadataJobDocument, { + metadataId, + }); return { query, metadataId, metadataDetails, userMetadataDetails }; }; @@ -314,11 +319,6 @@ export default function Page() { <Container> <MediaDetailsLayout images={loaderData.metadataDetails.assets.images} - entityDetails={{ - id: loaderData.metadataId, - lot: EntityLot.Metadata, - isPartial: loaderData.metadataDetails.isPartial, - }} externalLink={{ source: loaderData.metadataDetails.source, lot: loaderData.metadataDetails.lot, diff --git a/apps/frontend/app/routes/_dashboard.media.people.item.$id._index.tsx b/apps/frontend/app/routes/_dashboard.media.people.item.$id._index.tsx index a0b434f757..89e01c5651 100644 --- a/apps/frontend/app/routes/_dashboard.media.people.item.$id._index.tsx +++ b/apps/frontend/app/routes/_dashboard.media.people.item.$id._index.tsx @@ -14,6 +14,7 @@ import { import type { LoaderFunctionArgs, MetaArgs } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; import { + DeployUpdatePersonJobDocument, EntityLot, PersonDetailsDocument, UserPersonDetailsDocument, @@ -57,6 +58,10 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => { personId, }), ]); + if (personDetails.details.isPartial) + await serverGqlService.request(DeployUpdatePersonJobDocument, { + personId, + }); return { query, personId, userPersonDetails, personDetails }; }; @@ -82,11 +87,6 @@ export default function Page() { <Container> <MediaDetailsLayout images={loaderData.personDetails.details.displayImages} - entityDetails={{ - id: loaderData.personId, - lot: EntityLot.Person, - isPartial: loaderData.personDetails.details.isPartial, - }} externalLink={{ source: loaderData.personDetails.details.source, href: loaderData.personDetails.sourceUrl, diff --git a/apps/frontend/app/routes/actions.tsx b/apps/frontend/app/routes/actions.tsx index 87c5586aee..2901c11191 100644 --- a/apps/frontend/app/routes/actions.tsx +++ b/apps/frontend/app/routes/actions.tsx @@ -336,7 +336,6 @@ export const action = async ({ request }: ActionFunctionArgs) => { e.seasonNumber === submission.showSeasonNumber && e.episodeNumber === submission.showEpisodeNumber, ); - invariant(selectedEpisodeIndex !== -1); const firstEpisodeOfShow = allEpisodesInShow[0]; const lastSeenEpisode = latestHistoryItem?.showExtraInformation || { episode: firstEpisodeOfShow.episodeNumber, @@ -347,7 +346,6 @@ export const action = async ({ request }: ActionFunctionArgs) => { e.seasonNumber === lastSeenEpisode.season && e.episodeNumber === lastSeenEpisode.episode, ); - invariant(lastSeenEpisodeIndex !== -1); const firstEpisodeIndexToMark = lastSeenEpisodeIndex + (latestHistoryItem ? 1 : 0); if (selectedEpisodeIndex > firstEpisodeIndexToMark) { diff --git a/apps/frontend/app/routes/auth.tsx b/apps/frontend/app/routes/auth.tsx index d7117bc1f6..ce12194341 100644 --- a/apps/frontend/app/routes/auth.tsx +++ b/apps/frontend/app/routes/auth.tsx @@ -14,6 +14,7 @@ import { type ActionFunctionArgs, type LoaderFunctionArgs, type MetaArgs, + data, redirect, } from "@remix-run/node"; import { Form, Link, useLoaderData, useSearchParams } from "@remix-run/react"; @@ -102,8 +103,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { schema: registerSchema, }); if (submission.status !== "success") - return Response.json({} as const, { - status: 400, + return data({} as const, { headers: await createToastHeaders({ type: "error", message: @@ -133,8 +133,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { () => "This username already exists", ) .exhaustive(); - return Response.json({} as const, { - status: 400, + return data({} as const, { headers: await createToastHeaders({ message, type: "error" }), }); } @@ -176,7 +175,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { () => "The provider chosen was incorrect", ) .exhaustive(); - return Response.json({} as const, { + return data({} as const, { headers: await createToastHeaders({ message, type: "error" }), }); }) diff --git a/apps/website/app/routes/features.tsx b/apps/website/app/routes/features.tsx index c06528c238..89fe233054 100644 --- a/apps/website/app/routes/features.tsx +++ b/apps/website/app/routes/features.tsx @@ -1,5 +1,5 @@ import type { LoaderFunctionArgs, MetaArgs } from "@remix-run/node"; -import { cn } from "@ryot/ts-utils"; +import { cn, snakeCase } from "@ryot/ts-utils"; import Autoplay from "embla-carousel-autoplay"; import { LucideAmpersands, @@ -69,6 +69,7 @@ export default function Page() { {dataToDisplay.map((data, index) => ( <div key={data.heading} + id={snakeCase(data.heading)} className={cn( "py-10 space-y-4 md:space-y-8", index % 2 === 1 ? "bg-muted" : "bg-white", diff --git a/crates/models/media/src/lib.rs b/crates/models/media/src/lib.rs index 20c7fdac3d..e8637e2715 100644 --- a/crates/models/media/src/lib.rs +++ b/crates/models/media/src/lib.rs @@ -1545,9 +1545,3 @@ pub struct DailyUserActivityItem { pub total_count: i64, pub total_duration: i64, } - -#[derive(Debug, Ord, PartialEq, Eq, PartialOrd, Clone, Hash)] -pub struct CommitCache { - pub id: String, - pub lot: EntityLot, -} diff --git a/crates/services/miscellaneous/src/lib.rs b/crates/services/miscellaneous/src/lib.rs index ddb4ccc1f1..a95d6e3164 100644 --- a/crates/services/miscellaneous/src/lib.rs +++ b/crates/services/miscellaneous/src/lib.rs @@ -1135,7 +1135,7 @@ ORDER BY RANDOM() LIMIT 10; input: Vec<ProgressUpdateInput>, ) -> Result<bool> { for seen in input { - progress_update(seen, &user_id, false, &self.0) + progress_update(&user_id, false, seen, &self.0) .await .trace_ok(); } diff --git a/crates/services/supporting/Cargo.toml b/crates/services/supporting/Cargo.toml index 9a1e6c4692..ca5ba20547 100644 --- a/crates/services/supporting/Cargo.toml +++ b/crates/services/supporting/Cargo.toml @@ -11,7 +11,5 @@ cache-service = { path = "../../services/cache" } chrono-tz = { workspace = true } config = { path = "../../config" } file-storage-service = { path = "../../services/file-storage" } -media-models = { path = "../../models/media" } -moka = { workspace = true } openidconnect = { workspace = true } sea-orm = { workspace = true } diff --git a/crates/services/supporting/src/lib.rs b/crates/services/supporting/src/lib.rs index 717cf75901..f4699086d8 100644 --- a/crates/services/supporting/src/lib.rs +++ b/crates/services/supporting/src/lib.rs @@ -5,8 +5,6 @@ use async_graphql::Result; use background::{ApplicationJob, CoreApplicationJob}; use cache_service::CacheService; use file_storage_service::FileStorageService; -use media_models::CommitCache; -use moka::future::Cache; use openidconnect::core::CoreClient; use sea_orm::DatabaseConnection; @@ -17,7 +15,6 @@ pub struct SupportingService { pub cache_service: CacheService, pub config: Arc<config::AppConfig>, pub oidc_client: Option<CoreClient>, - pub commit_cache: Cache<CommitCache, ()>, pub file_storage_service: Arc<FileStorageService>, perform_application_job: MemoryStorage<ApplicationJob>, @@ -33,7 +30,6 @@ impl SupportingService { cache_service: CacheService, config: Arc<config::AppConfig>, oidc_client: Option<CoreClient>, - commit_cache: Cache<CommitCache, ()>, file_storage_service: Arc<FileStorageService>, perform_application_job: &MemoryStorage<ApplicationJob>, perform_core_application_job: &MemoryStorage<CoreApplicationJob>, @@ -43,7 +39,6 @@ impl SupportingService { is_pro, timezone, oidc_client, - commit_cache, cache_service, db: db.clone(), file_storage_service, diff --git a/crates/utils/dependent/src/lib.rs b/crates/utils/dependent/src/lib.rs index c05a26ed4a..e94345d27e 100644 --- a/crates/utils/dependent/src/lib.rs +++ b/crates/utils/dependent/src/lib.rs @@ -39,9 +39,9 @@ use fitness_models::{ use importer_models::{ImportDetails, ImportFailStep, ImportFailedItem, ImportResultResponse}; use itertools::Itertools; use media_models::{ - CommitCache, CommitMediaInput, CommitPersonInput, CreateOrUpdateCollectionInput, - CreateOrUpdateReviewInput, ImportOrExportItemRating, MetadataDetails, MetadataImage, - PartialMetadata, PartialMetadataPerson, PartialMetadataWithoutId, ProgressUpdateError, + CommitMediaInput, CommitPersonInput, CreateOrUpdateCollectionInput, CreateOrUpdateReviewInput, + ImportOrExportItemRating, MetadataDetails, MetadataImage, PartialMetadata, + PartialMetadataPerson, PartialMetadataWithoutId, ProgressUpdateError, ProgressUpdateErrorVariant, ProgressUpdateInput, ProgressUpdateResultUnion, ReviewPostedEvent, SeenAnimeExtraInformation, SeenMangaExtraInformation, SeenPodcastExtraInformation, SeenShowExtraInformation, @@ -692,8 +692,8 @@ pub async fn get_users_and_cte_monitoring_entity( ) -> Result<Vec<(String, Uuid)>> { let all_entities = MonitoredEntity::find() .select_only() - .column(monitored_entity::Column::CollectionToEntityId) .column(monitored_entity::Column::UserId) + .column(monitored_entity::Column::CollectionToEntityId) .filter(monitored_entity::Column::EntityId.eq(entity_id)) .filter(monitored_entity::Column::EntityLot.eq(entity_lot)) .into_tuple::<(String, Uuid)>() @@ -875,19 +875,10 @@ pub async fn commit_metadata( let media = commit_metadata_internal(details, None, ss).await?; return Ok(media); }; - let cached_metadata = CommitCache { - id: m.id.clone(), - lot: EntityLot::Metadata, - }; - if ss.commit_cache.get(&cached_metadata).await.is_some() { - return Ok(m); - } - ss.commit_cache.insert(cached_metadata.clone(), ()).await; if input.force_update.unwrap_or_default() { ryot_log!(debug, "Forcing update of metadata with id {}", &m.id); update_metadata_and_notify_users(&m.id, true, ss).await?; } - ss.commit_cache.remove(&cached_metadata).await; Ok(m) } @@ -1293,10 +1284,10 @@ pub async fn handle_after_media_seen_tasks( } pub async fn progress_update( - input: ProgressUpdateInput, user_id: &String, // update only if media has not been consumed for this user in the last `n` duration respect_cache: bool, + input: ProgressUpdateInput, ss: &Arc<SupportingService>, ) -> Result<ProgressUpdateResultUnion> { let cache = ApplicationCacheKey::ProgressUpdateCache { @@ -2020,6 +2011,8 @@ pub async fn process_import( Some(dec!(100)) }; if let Err(e) = progress_update( + user_id, + respect_cache, ProgressUpdateInput { metadata_id: metadata.id.clone(), progress, @@ -2033,8 +2026,6 @@ pub async fn process_import( provider_watched_on: seen.provider_watched_on.clone(), change_state: None, }, - user_id, - respect_cache, ss, ) .await @@ -2086,8 +2077,8 @@ pub async fn process_import( for (idx, item) in import.metadata_groups.into_iter().enumerate() { ryot_log!( debug, - "Importing media group with identifier = {iden}", - iden = &item.title + "Importing media group with identifier = {identifier}", + identifier = &item.title ); let rev_length = item.reviews.len(); let data =