@@ -326,32 +326,51 @@ impl Database {
326
326
Ok ( Self { conn } )
327
327
}
328
328
329
- /// Insert `entry` under `id` into the database and optionally set owner to `uid`.
330
- pub async fn insert ( & self , id : Id , entry : write:: Entry ) -> Result < ( ) , Error > {
329
+ /// Insert `entry` with a new generated `id` into the database and optionally set owner to `uid`.
330
+ pub async fn insert ( & self , entry : write:: Entry ) -> Result < ( Id , write :: Entry ) , Error > {
331
331
let conn = self . conn . clone ( ) ;
332
332
let write:: DatabaseEntry { entry, data, nonce } = entry. compress ( ) . await ?. encrypt ( ) . await ?;
333
333
334
- spawn_blocking ( move || match entry. expires {
335
- None => conn. lock ( ) . execute (
336
- "INSERT INTO entries (id, uid, data, burn_after_reading, nonce, title) VALUES (?1, ?2, ?3, ?4, ?5, ?6)" ,
337
- params ! [ id. to_i64( ) , entry. uid, data, entry. burn_after_reading, nonce, entry. title] ,
338
- ) ,
339
- Some ( expires) => conn. lock ( ) . execute (
340
- "INSERT INTO entries (id, uid, data, burn_after_reading, nonce, expires, title) VALUES (?1, ?2, ?3, ?4, ?5, datetime('now', ?6), ?7)" ,
341
- params ! [
342
- id. to_i64( ) ,
343
- entry. uid,
344
- data,
345
- entry. burn_after_reading,
346
- nonce,
347
- format!( "{expires} seconds" ) ,
348
- entry. title,
349
- ] ,
350
- ) ,
351
- } )
352
- . await ??;
334
+ let title = entry. title . clone ( ) ;
335
+
336
+ let id = spawn_blocking ( move || {
337
+ let mut counter = 0 ;
338
+
339
+ loop {
340
+ let id = Id :: rand ( ) ;
341
+
342
+ let result = match entry. expires {
343
+ None => conn. lock ( ) . execute (
344
+ "INSERT INTO entries (id, uid, data, burn_after_reading, nonce, title) VALUES (?1, ?2, ?3, ?4, ?5, ?6)" ,
345
+ params ! [ id. to_i64( ) , entry. uid, data, entry. burn_after_reading, nonce, title] ,
346
+ ) ,
347
+ Some ( expires) => conn. lock ( ) . execute (
348
+ "INSERT INTO entries (id, uid, data, burn_after_reading, nonce, expires, title) VALUES (?1, ?2, ?3, ?4, ?5, datetime('now', ?6), ?7)" ,
349
+ params ! [
350
+ id. to_i64( ) ,
351
+ entry. uid,
352
+ data,
353
+ entry. burn_after_reading,
354
+ nonce,
355
+ format!( "{expires} seconds" ) ,
356
+ title,
357
+ ] ,
358
+ ) ,
359
+ } ;
360
+
361
+ match result {
362
+ Err ( rusqlite:: Error :: SqliteFailure ( rusqlite:: ffi:: Error { code, extended_code } , Some ( ref _message) ) ) if code == rusqlite:: ErrorCode :: ConstraintViolation && extended_code == 1555 && counter < 10 => {
363
+ /* Retry if ID is already existent */
364
+ counter += 1 ;
365
+ continue ;
366
+ } ,
367
+ Err ( err) => break Err ( err) ,
368
+ Ok ( rows) => { debug_assert ! ( rows == 1 ) ; break Ok ( id) } ,
369
+ }
370
+ }
371
+ } ) . await ??;
353
372
354
- Ok ( ( ) )
373
+ Ok ( ( id , entry ) )
355
374
}
356
375
357
376
/// Get entire entry for `id`.
@@ -532,8 +551,7 @@ mod tests {
532
551
..Default :: default ( )
533
552
} ;
534
553
535
- let id = Id :: from ( 1234u32 ) ;
536
- db. insert ( id, entry) . await ?;
554
+ let ( id, _entry) = db. insert ( entry) . await ?;
537
555
538
556
let entry = db. get ( id, None ) . await ?. unwrap_inner ( ) ;
539
557
assert_eq ! ( entry. text, "hello world" ) ;
@@ -555,8 +573,7 @@ mod tests {
555
573
..Default :: default ( )
556
574
} ;
557
575
558
- let id = Id :: from ( 1234u32 ) ;
559
- db. insert ( id, entry) . await ?;
576
+ let ( id, _entry) = db. insert ( entry) . await ?;
560
577
561
578
tokio:: time:: sleep ( tokio:: time:: Duration :: from_secs ( 2 ) ) . await ;
562
579
@@ -570,8 +587,7 @@ mod tests {
570
587
async fn delete ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
571
588
let db = new_db ( ) ?;
572
589
573
- let id = Id :: from ( 1234u32 ) ;
574
- db. insert ( id, write:: Entry :: default ( ) ) . await ?;
590
+ let ( id, _entry) = db. insert ( write:: Entry :: default ( ) ) . await ?;
575
591
576
592
assert ! ( db. get( id, None ) . await . is_ok( ) ) ;
577
593
assert ! ( db. delete( id) . await . is_ok( ) ) ;
@@ -589,14 +605,13 @@ mod tests {
589
605
..Default :: default ( )
590
606
} ;
591
607
592
- let id = Id :: from ( 1234u32 ) ;
593
- db. insert ( id, entry) . await ?;
608
+ let ( id, _entry) = db. insert ( entry) . await ?;
594
609
595
610
tokio:: time:: sleep ( tokio:: time:: Duration :: from_secs ( 2 ) ) . await ;
596
611
597
612
let ids = db. purge ( ) ?;
598
613
assert_eq ! ( ids. len( ) , 1 ) ;
599
- assert_eq ! ( ids[ 0 ] . to_i64 ( ) , 1234 ) ;
614
+ assert_eq ! ( ids[ 0 ] , id ) ;
600
615
601
616
Ok ( ( ) )
602
617
}
0 commit comments