1616
1717import logging
1818import os
19- from typing import Annotated
19+ from typing import Annotated , Type
2020
21+ from deepdiff import DeepDiff
2122from fastapi import HTTPException
2223from pydantic import Field
2324from starlette .responses import Response
2425
25- from database_gen .sqlacodegen_models import Gtfsfeed
26+ from database_gen .sqlacodegen_models import Gtfsfeed , t_feedsearch
2627from feeds_operations .impl .models .update_request_gtfs_feed_impl import (
2728 UpdateRequestGtfsFeedImpl ,
2829)
29- from .request_validator import validate_request
3030from feeds_operations_gen .apis .operations_api_base import BaseOperationsApi
3131from feeds_operations_gen .models .data_type import DataType
3232from feeds_operations_gen .models .update_request_gtfs_feed import UpdateRequestGtfsFeed
33- from helpers .database import start_db_session
33+ from feeds_operations_gen .models .update_request_gtfs_rt_feed import (
34+ UpdateRequestGtfsRtFeed ,
35+ )
36+ from helpers .database import start_db_session , refresh_materialized_view
3437from helpers .query_helper import query_feed_by_stable_id
35- from deepdiff import DeepDiff
38+ from .models .update_request_gtfs_rt_feed_impl import UpdateRequestGtfsRtFeedImpl
39+ from .request_validator import validate_request
3640
3741logging .basicConfig (level = logging .INFO )
3842
@@ -44,20 +48,22 @@ class OperationsApiImpl(BaseOperationsApi):
4448
4549 @staticmethod
4650 def detect_changes (
47- feed : Gtfsfeed , update_request_gtfs_feed : UpdateRequestGtfsFeed
51+ feed : Gtfsfeed ,
52+ update_request_feed : UpdateRequestGtfsFeed | UpdateRequestGtfsRtFeed ,
53+ impl_class : Type [UpdateRequestGtfsFeedImpl ] | Type [UpdateRequestGtfsRtFeedImpl ],
4854 ) -> DeepDiff :
4955 """
5056 Detect changes between the feed and the update request.
5157 """
5258 # Normalize the feed and the update request and compare them
53- copy_feed = UpdateRequestGtfsFeedImpl .from_orm (feed )
59+ copy_feed = impl_class .from_orm (feed )
5460 # Temporary solution to update the operational status
5561 copy_feed .operational_status_action = (
56- update_request_gtfs_feed .operational_status_action
62+ update_request_feed .operational_status_action
5763 )
5864 diff = DeepDiff (
5965 copy_feed .model_dump (),
60- update_request_gtfs_feed .model_dump (),
66+ update_request_feed .model_dump (),
6167 ignore_order = True ,
6268 )
6369 if diff .affected_paths :
@@ -68,7 +74,7 @@ def detect_changes(
6874 logging .info ("Detect update changes: no changes detected" )
6975 return diff
7076
71- @validate_request (UpdateRequestGtfsFeed , "update_request_gtfs_feed" )
77+ @validate_request (Type [ UpdateRequestGtfsFeed ] , "update_request_gtfs_feed" )
7278 async def update_gtfs_feed (
7379 self ,
7480 update_request_gtfs_feed : Annotated [
@@ -84,36 +90,67 @@ async def update_gtfs_feed(
8490 - 500: Internal server error.
8591 """
8692 ...
93+ return await self ._update_feed (update_request_gtfs_feed , DataType .GTFS )
94+
95+ @validate_request (Type [UpdateRequestGtfsRtFeed ], "update_request_gtfs_rt_feed" )
96+ async def update_gtfs_rt_feed (
97+ self ,
98+ update_request_gtfs_rt_feed : Annotated [
99+ UpdateRequestGtfsRtFeed ,
100+ Field (description = "Payload to update the specified GTFS-RT feed." ),
101+ ],
102+ ) -> Response :
103+ """Update the specified GTFS-RT feed in the Mobility Database.
104+ returns:
105+ - 200: Feed updated successfully.
106+ - 204: No changes detected.
107+ - 400: Feed ID not found.
108+ - 500: Internal server error.
109+ """
110+ return await self ._update_feed (update_request_gtfs_rt_feed , DataType .GTFS_RT )
111+
112+ async def _update_feed (
113+ self ,
114+ update_request_feed : UpdateRequestGtfsFeed | UpdateRequestGtfsRtFeed ,
115+ data_type : DataType ,
116+ ) -> Response :
117+ """
118+ Update the specified feed in the Mobility Database
119+ """
87120 session = None
88121 try :
89122 session = start_db_session (os .getenv ("FEEDS_DATABASE_URL" ))
90123 feed : Gtfsfeed = query_feed_by_stable_id (
91- session , update_request_gtfs_feed .id , DataType . GTFS .name
124+ session , update_request_feed .id , data_type .name
92125 )
93126 if feed is None :
94127 raise HTTPException (
95128 status_code = 400 ,
96- detail = f"Feed ID not found: { update_request_gtfs_feed .id } " ,
129+ detail = f"Feed ID not found: { update_request_feed .id } " ,
97130 )
98131
99132 logging .info (
100- f"Feed ID: { id } attempting to update with the following request: { update_request_gtfs_feed } "
133+ f"Feed ID: { id } attempting to update with the following request: { update_request_feed } "
101134 )
102- diff = self .detect_changes (feed , update_request_gtfs_feed )
135+ impl_class = (
136+ UpdateRequestGtfsFeedImpl
137+ if data_type == DataType .GTFS
138+ else UpdateRequestGtfsRtFeedImpl
139+ )
140+ diff = self .detect_changes (feed , update_request_feed , impl_class )
103141 if len (diff .affected_paths ) > 0 or (
104- update_request_gtfs_feed .operational_status_action is not None
105- and update_request_gtfs_feed .operational_status_action != "no_change"
142+ update_request_feed .operational_status_action is not None
143+ and update_request_feed .operational_status_action != "no_change"
106144 ):
107- UpdateRequestGtfsFeedImpl .to_orm (
108- update_request_gtfs_feed , feed , session
109- )
145+ impl_class .to_orm (update_request_feed , feed , session )
110146 # This is a temporary solution as the operational_status is not visible in the diff
111147 feed .operational_status = (
112148 feed .operational_status
113- if update_request_gtfs_feed .operational_status_action == "no_change"
114- else update_request_gtfs_feed .operational_status_action
149+ if update_request_feed .operational_status_action == "no_change"
150+ else update_request_feed .operational_status_action
115151 )
116152 session .add (feed )
153+ refresh_materialized_view (session , t_feedsearch .name )
117154 session .commit ()
118155 logging .info (
119156 f"Feed ID: { id } updated successfully with the following changes: { diff .values ()} "
0 commit comments