@@ -29,7 +29,7 @@ use spacetimedb::messages::control_db::{Database, HostType};
2929use spacetimedb_client_api_messages:: name:: { self , DatabaseName , DomainName , PublishOp , PublishResult } ;
3030use spacetimedb_lib:: db:: raw_def:: v9:: RawModuleDefV9 ;
3131use spacetimedb_lib:: identity:: AuthCtx ;
32- use spacetimedb_lib:: sats;
32+ use spacetimedb_lib:: { sats, Timestamp } ;
3333
3434use super :: subscribe:: handle_websocket;
3535
@@ -732,6 +732,33 @@ pub async fn set_names<S: ControlStateDelegate>(
732732 Ok ( ( status, axum:: Json ( response) ) )
733733}
734734
735+ #[ derive( serde:: Deserialize ) ]
736+ pub struct TimestampParams {
737+ name_or_identity : NameOrIdentity ,
738+ }
739+
740+ /// Returns the database's view of the current time,
741+ /// as a SATS-JSON encoded [`Timestamp`].
742+ ///
743+ /// Takes a particular database's [`NameOrIdentity`] as an argument
744+ /// because in a clusterized SpacetimeDB-cloud deployment,
745+ /// this request will be routed to the node running the requested database.
746+ async fn get_timestamp < S : ControlStateDelegate > (
747+ State ( worker_ctx) : State < S > ,
748+ Path ( TimestampParams { name_or_identity } ) : Path < TimestampParams > ,
749+ ) -> axum:: response:: Result < impl IntoResponse > {
750+ let db_identity = name_or_identity. resolve ( & worker_ctx) . await ?;
751+
752+ let _database = worker_ctx_find_database ( & worker_ctx, & db_identity)
753+ . await ?
754+ . ok_or_else ( || {
755+ log:: error!( "Could not find database: {}" , db_identity. to_hex( ) ) ;
756+ NO_SUCH_DATABASE
757+ } ) ?;
758+
759+ Ok ( axum:: Json ( sats:: serde:: SerdeWrapper ( Timestamp :: now ( ) ) ) . into_response ( ) )
760+ }
761+
735762/// This struct allows the edition to customize `/database` routes more meticulously.
736763pub struct DatabaseRoutes < S > {
737764 /// POST /database
@@ -760,6 +787,9 @@ pub struct DatabaseRoutes<S> {
760787 pub logs_get : MethodRouter < S > ,
761788 /// POST: /database/:name_or_identity/sql
762789 pub sql_post : MethodRouter < S > ,
790+
791+ /// GET: /database/: name_or_identity/unstable/timestamp
792+ pub timestamp_get : MethodRouter < S > ,
763793}
764794
765795impl < S > Default for DatabaseRoutes < S >
@@ -782,6 +812,7 @@ where
782812 schema_get : get ( schema :: < S > ) ,
783813 logs_get : get ( logs :: < S > ) ,
784814 sql_post : post ( sql :: < S > ) ,
815+ timestamp_get : get ( get_timestamp :: < S > ) ,
785816 }
786817 }
787818}
@@ -803,7 +834,8 @@ where
803834 . route ( "/call/:reducer" , self . call_reducer_post )
804835 . route ( "/schema" , self . schema_get )
805836 . route ( "/logs" , self . logs_get )
806- . route ( "/sql" , self . sql_post ) ;
837+ . route ( "/sql" , self . sql_post )
838+ . route ( "/unstable/timestamp" , self . timestamp_get ) ;
807839
808840 axum:: Router :: new ( )
809841 . route ( "/" , self . root_post )
0 commit comments