@@ -134,40 +134,30 @@ impl RepoHandle {
134
134
}
135
135
136
136
/// Create a new document.
137
- pub fn new_document ( & self ) -> DocHandle {
137
+ pub fn new_document ( & self ) -> impl Future < Output = DocHandle > {
138
138
let document_id = DocumentId :: random ( ) ;
139
139
let document = new_document ( ) ;
140
- let doc_info = self . new_document_info ( document, DocState :: Sync ( vec ! [ ] ) ) ;
141
- let handle = DocHandle :: new (
142
- self . repo_sender . clone ( ) ,
143
- document_id. clone ( ) ,
144
- doc_info. document . clone ( ) ,
145
- doc_info. handle_count . clone ( ) ,
146
- self . repo_id . clone ( ) ,
147
- ) ;
140
+ let ( future, resolver) = new_repo_future_with_resolver ( ) ;
148
141
self . repo_sender
149
- . send ( RepoEvent :: NewDoc ( document_id, doc_info) )
142
+ . send ( RepoEvent :: NewDoc (
143
+ document_id,
144
+ SharedDocument {
145
+ automerge : document,
146
+ } ,
147
+ resolver,
148
+ ) )
150
149
. expect ( "Failed to send repo event." ) ;
151
- // TODO: return a future to make-up for the unboundedness of the channel.
152
- handle
150
+ future
153
151
}
154
152
155
153
/// Boostrap a document, first from storage, and if not found over the network.
156
154
pub fn request_document (
157
155
& self ,
158
156
document_id : DocumentId ,
159
- ) -> RepoFuture < Result < Option < DocHandle > , RepoError > > {
160
- let document = new_document ( ) ;
157
+ ) -> impl Future < Output = Result < Option < DocHandle > , RepoError > > {
161
158
let ( fut, resolver) = new_repo_future_with_resolver ( ) ;
162
- let doc_info = self . new_document_info (
163
- document,
164
- DocState :: Bootstrap {
165
- resolvers : vec ! [ resolver] ,
166
- storage_fut : None ,
167
- } ,
168
- ) ;
169
159
self . repo_sender
170
- . send ( RepoEvent :: NewDoc ( document_id, doc_info ) )
160
+ . send ( RepoEvent :: RequestDoc ( document_id, resolver ) )
171
161
. expect ( "Failed to send repo event." ) ;
172
162
fut
173
163
}
@@ -186,15 +176,6 @@ impl RepoHandle {
186
176
fut
187
177
}
188
178
189
- fn new_document_info ( & self , document : Automerge , state : DocState ) -> DocumentInfo {
190
- let document = SharedDocument {
191
- automerge : document,
192
- } ;
193
- let document = Arc :: new ( RwLock :: new ( document) ) ;
194
- let handle_count = Arc :: new ( AtomicUsize :: new ( 1 ) ) ;
195
- DocumentInfo :: new ( state, document, handle_count)
196
- }
197
-
198
179
/// Add a network adapter, representing a connection with a remote repo.
199
180
pub fn new_remote_repo (
200
181
& self ,
@@ -215,7 +196,12 @@ impl RepoHandle {
215
196
/// Events sent by repo or doc handles to the repo.
216
197
pub ( crate ) enum RepoEvent {
217
198
/// Start processing a new document.
218
- NewDoc ( DocumentId , DocumentInfo ) ,
199
+ NewDoc ( DocumentId , SharedDocument , RepoFutureResolver < DocHandle > ) ,
200
+ /// Request a document we don't have
201
+ RequestDoc (
202
+ DocumentId ,
203
+ RepoFutureResolver < Result < Option < DocHandle > , RepoError > > ,
204
+ ) ,
219
205
/// A document changed.
220
206
DocChange ( DocumentId ) ,
221
207
/// A document was closed(all doc handles dropped).
@@ -246,7 +232,8 @@ pub(crate) enum RepoEvent {
246
232
impl fmt:: Debug for RepoEvent {
247
233
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
248
234
match self {
249
- RepoEvent :: NewDoc ( _, _) => f. write_str ( "RepoEvent::NewDoc" ) ,
235
+ RepoEvent :: NewDoc ( _, _, _) => f. write_str ( "RepoEvent::NewDoc" ) ,
236
+ RepoEvent :: RequestDoc ( _, _) => f. write_str ( "RepoEvent::RequestDoc" ) ,
250
237
RepoEvent :: DocChange ( _) => f. write_str ( "RepoEvent::DocChange" ) ,
251
238
RepoEvent :: DocClosed ( _) => f. write_str ( "RepoEvent::DocClosed" ) ,
252
239
RepoEvent :: AddChangeObserver ( _, _, _) => f. write_str ( "RepoEvent::AddChangeObserver" ) ,
@@ -367,17 +354,6 @@ impl DocState {
367
354
}
368
355
}
369
356
370
- fn get_bootstrap_resolvers (
371
- & mut self ,
372
- ) -> Vec < RepoFutureResolver < Result < Option < DocHandle > , RepoError > > > {
373
- match self {
374
- DocState :: Bootstrap { resolvers, .. } => mem:: take ( resolvers) ,
375
- _ => unreachable ! (
376
- "Trying to get boostrap resolvers from a document that cannot have any."
377
- ) ,
378
- }
379
- }
380
-
381
357
fn resolve_bootstrap_fut ( & mut self , doc_handle : Result < DocHandle , RepoError > ) {
382
358
match self {
383
359
DocState :: Bootstrap { resolvers, .. } => {
@@ -468,38 +444,6 @@ impl DocState {
468
444
}
469
445
}
470
446
471
- fn add_boostrap_storage_fut (
472
- & mut self ,
473
- fut : BoxFuture < ' static , Result < Option < Vec < u8 > > , StorageError > > ,
474
- ) {
475
- match self {
476
- DocState :: Bootstrap {
477
- resolvers : _,
478
- ref mut storage_fut,
479
- } => {
480
- assert ! ( storage_fut. is_none( ) ) ;
481
- * storage_fut = Some ( fut) ;
482
- }
483
- _ => unreachable ! (
484
- "Trying to add a boostrap load future for a document that does not need one."
485
- ) ,
486
- }
487
- }
488
-
489
- fn add_boostrap_resolvers (
490
- & mut self ,
491
- incoming : & mut Vec < RepoFutureResolver < Result < Option < DocHandle > , RepoError > > > ,
492
- ) {
493
- match self {
494
- DocState :: Bootstrap {
495
- ref mut resolvers, ..
496
- } => {
497
- resolvers. append ( incoming) ;
498
- }
499
- _ => unreachable ! ( "Unexpected adding of boostrap resolvers." ) ,
500
- }
501
- }
502
-
503
447
fn poll_pending_save ( & mut self , waker : Arc < RepoWaker > ) {
504
448
assert ! ( matches!( * waker, RepoWaker :: Storage { .. } ) ) ;
505
449
match self {
@@ -645,10 +589,6 @@ impl DocumentInfo {
645
589
}
646
590
}
647
591
648
- fn is_boostrapping ( & self ) -> bool {
649
- self . state . is_bootstrapping ( )
650
- }
651
-
652
592
fn start_pending_removal ( & mut self ) {
653
593
self . state = match & mut self . state {
654
594
DocState :: Error | DocState :: LoadPending { .. } | DocState :: Bootstrap { .. } => {
@@ -1330,61 +1270,91 @@ impl Repo {
1330
1270
fn handle_repo_event ( & mut self , event : RepoEvent ) {
1331
1271
tracing:: trace!( event = ?event, "Handling repo event" ) ;
1332
1272
match event {
1333
- // TODO: simplify handling of `RepoEvent::NewDoc`.
1334
- // `NewDoc` could be broken-up into two events: `RequestDoc` and `NewDoc`,
1335
- // the doc info could be created here.
1336
- RepoEvent :: NewDoc ( document_id, mut info) => {
1337
- if info. is_boostrapping ( ) {
1338
- tracing:: trace!( "adding bootstrapping document" ) ;
1339
- if let Some ( existing_info) = self . documents . get_mut ( & document_id) {
1340
- if matches ! ( existing_info. state, DocState :: Bootstrap { .. } ) {
1341
- let mut resolvers = info. state . get_bootstrap_resolvers ( ) ;
1342
- existing_info. state . add_boostrap_resolvers ( & mut resolvers) ;
1343
- } else if matches ! ( existing_info. state, DocState :: Sync ( _) ) {
1344
- existing_info. handle_count . fetch_add ( 1 , Ordering :: SeqCst ) ;
1345
- let handle = DocHandle :: new (
1346
- self . repo_sender . clone ( ) ,
1347
- document_id. clone ( ) ,
1348
- existing_info. document . clone ( ) ,
1349
- existing_info. handle_count . clone ( ) ,
1350
- self . repo_id . clone ( ) ,
1351
- ) ;
1352
- info. state . resolve_bootstrap_fut ( Ok ( handle) ) ;
1353
- } else {
1354
- tracing:: warn!( state=?info. state, "newdoc event received for existing document with incorrect state" ) ;
1355
- info. state . resolve_bootstrap_fut ( Err ( RepoError :: Incorrect ( format ! ( "newdoc event received for existing document with incorrect state: {:?}" , info. state) ) ) ) ;
1356
- }
1357
- return ;
1358
- } else {
1273
+ RepoEvent :: NewDoc ( document_id, document, mut resolver) => {
1274
+ assert ! (
1275
+ self . documents. get( & document_id) . is_none( ) ,
1276
+ "NewDoc event should be sent with a fresh document ID and only be sent once"
1277
+ ) ;
1278
+ let shared = Arc :: new ( RwLock :: new ( document) ) ;
1279
+ let handle_count = Arc :: new ( AtomicUsize :: new ( 1 ) ) ;
1280
+ let info =
1281
+ DocumentInfo :: new ( DocState :: Sync ( vec ! [ ] ) , shared. clone ( ) , handle_count. clone ( ) ) ;
1282
+ self . documents . insert ( document_id. clone ( ) , info) ;
1283
+ resolver. resolve_fut ( DocHandle :: new (
1284
+ self . repo_sender . clone ( ) ,
1285
+ document_id. clone ( ) ,
1286
+ shared. clone ( ) ,
1287
+ handle_count. clone ( ) ,
1288
+ self . repo_id . clone ( ) ,
1289
+ ) ) ;
1290
+ Self :: enqueue_share_decisions (
1291
+ self . remote_repos . keys ( ) ,
1292
+ & mut self . pending_share_decisions ,
1293
+ & mut self . share_decisions_to_poll ,
1294
+ self . share_policy . as_ref ( ) ,
1295
+ document_id,
1296
+ ShareType :: Announce ,
1297
+ ) ;
1298
+ }
1299
+ RepoEvent :: RequestDoc ( document_id, mut resolver) => {
1300
+ let info = self
1301
+ . documents
1302
+ . entry ( document_id. clone ( ) )
1303
+ . or_insert_with ( || {
1304
+ let handle_count = Arc :: new ( AtomicUsize :: new ( 1 ) ) ;
1359
1305
let storage_fut = self . storage . get ( document_id. clone ( ) ) ;
1360
- info. state . add_boostrap_storage_fut ( storage_fut) ;
1306
+ let mut info = DocumentInfo :: new (
1307
+ DocState :: Bootstrap {
1308
+ resolvers : vec ! [ ] ,
1309
+ storage_fut : Some ( storage_fut) ,
1310
+ } ,
1311
+ Arc :: new ( RwLock :: new ( SharedDocument {
1312
+ automerge : new_document ( ) ,
1313
+ } ) ) ,
1314
+ handle_count. clone ( ) ,
1315
+ ) ;
1361
1316
info. poll_storage_operation (
1362
1317
document_id. clone ( ) ,
1363
1318
& self . wake_sender ,
1364
1319
& self . repo_sender ,
1365
1320
& self . repo_id ,
1366
1321
) ;
1367
1322
1368
- let share_type = if info. is_boostrapping ( ) {
1369
- Some ( ShareType :: Request )
1370
- } else if info. state . should_sync ( ) {
1371
- Some ( ShareType :: Announce )
1372
- } else {
1373
- None
1374
- } ;
1375
- if let Some ( share_type) = share_type {
1376
- Self :: enqueue_share_decisions (
1377
- self . remote_repos . keys ( ) ,
1378
- & mut self . pending_share_decisions ,
1379
- & mut self . share_decisions_to_poll ,
1380
- self . share_policy . as_ref ( ) ,
1381
- document_id. clone ( ) ,
1382
- share_type,
1383
- ) ;
1384
- }
1323
+ info
1324
+ } ) ;
1325
+
1326
+ match & mut info. state {
1327
+ DocState :: Bootstrap { resolvers, .. } => resolvers. push ( resolver) ,
1328
+ DocState :: Sync ( _) => {
1329
+ info. handle_count . fetch_add ( 1 , Ordering :: SeqCst ) ;
1330
+ let handle = DocHandle :: new (
1331
+ self . repo_sender . clone ( ) ,
1332
+ document_id. clone ( ) ,
1333
+ info. document . clone ( ) ,
1334
+ info. handle_count . clone ( ) ,
1335
+ self . repo_id . clone ( ) ,
1336
+ ) ;
1337
+ resolver. resolve_fut ( Ok ( Some ( handle) ) ) ;
1338
+ }
1339
+ DocState :: LoadPending { resolvers, .. } => resolvers. push ( resolver) ,
1340
+ DocState :: PendingRemoval ( _) => resolver. resolve_fut ( Ok ( None ) ) ,
1341
+ DocState :: Error => {
1342
+ resolver. resolve_fut ( Err ( RepoError :: Incorrect (
1343
+ "request event called for document which is in error state" . to_string ( ) ,
1344
+ ) ) ) ;
1385
1345
}
1386
1346
}
1387
- self . documents . insert ( document_id, info) ;
1347
+
1348
+ if info. state . is_bootstrapping ( ) {
1349
+ Self :: enqueue_share_decisions (
1350
+ self . remote_repos . keys ( ) ,
1351
+ & mut self . pending_share_decisions ,
1352
+ & mut self . share_decisions_to_poll ,
1353
+ self . share_policy . as_ref ( ) ,
1354
+ document_id. clone ( ) ,
1355
+ ShareType :: Request ,
1356
+ ) ;
1357
+ }
1388
1358
}
1389
1359
RepoEvent :: DocChange ( doc_id) => {
1390
1360
// Handle doc changes: sync the document.
0 commit comments