@@ -10,7 +10,8 @@ use std::{collections::HashMap, fmt, sync::Arc};
1010
1111use syncserver_common:: Metrics ;
1212use syncstorage_db_common:: {
13- diesel:: DbError , params, results, util:: SyncTimestamp , Db , UserIdentifier ,
13+ diesel:: DbError , error:: DbErrorIntrospect , params, results, util:: SyncTimestamp , Db ,
14+ UserIdentifier , FIRST_CUSTOM_COLLECTION_ID ,
1415} ;
1516use syncstorage_settings:: Quota ;
1617
@@ -98,30 +99,31 @@ impl PgDb {
9899 /// Gets the provided collection by name and creates it if not present.
99100 /// Checks collection cache first to see if matching collection stored.
100101 /// Uses logic to not make change sif there is a conflict during insert.
101- pub ( super ) async fn get_or_create_collection_id ( & mut self , name : & str ) -> DbResult < i32 > {
102- if let Some ( id) = self . coll_cache . get_id ( name) ? {
103- return Ok ( id) ;
102+ async fn get_or_create_collection_id ( & mut self , name : & str ) -> DbResult < i32 > {
103+ match self . get_collection_id ( name) . await {
104+ Err ( e) if e. is_collection_not_found ( ) => self . _create_collection ( name) . await ,
105+ result => result,
104106 }
107+ }
105108
106- // Postgres specific ON CONFLICT DO NOTHING statement.
107- // https://docs.diesel.rs/2.0.x/diesel/query_builder/struct.InsertStatement.html#method.on_conflict_do_nothing
108- diesel:: insert_into ( collections:: table)
109+ async fn _create_collection ( & mut self , name : & str ) -> DbResult < i32 > {
110+ if !cfg ! ( debug_assertions) && !self . session . in_write_transaction {
111+ return Err ( DbError :: internal (
112+ "Can't escalate read-lock to write-lock" . to_owned ( ) ,
113+ ) ) ;
114+ }
115+ let collection_id = diesel:: insert_into ( collections:: table)
109116 . values ( collections:: name. eq ( name) )
110- . on_conflict_do_nothing ( )
111- . execute ( & mut self . conn )
112- . await ?;
113-
114- let id = collections:: table
115- . select ( collections:: collection_id)
116- . filter ( collections:: name. eq ( name) )
117- . first ( & mut self . conn )
117+ . returning ( collections:: collection_id)
118+ . get_result ( & mut self . conn )
118119 . await ?;
119-
120- if !self . session . in_write_transaction {
121- self . coll_cache . put ( id, name. to_owned ( ) ) ?;
120+ if collection_id < FIRST_CUSTOM_COLLECTION_ID {
121+ // DDL ensures this should never occur
122+ return Err ( DbError :: internal (
123+ "create_collection < {FIRST_CUSTOM_COLLECTION_ID}" . to_owned ( ) ,
124+ ) ) ;
122125 }
123-
124- Ok ( id)
126+ Ok ( collection_id)
125127 }
126128
127129 /// Given a set of collection_ids, return a HashMap of collection_id's
0 commit comments