@@ -24,20 +24,19 @@ use quickwit_proto::metastore::{EntityKind, MetastoreError, MetastoreResult};
24
24
use quickwit_proto:: types:: IndexId ;
25
25
use quickwit_storage:: Storage ;
26
26
use tokio:: sync:: { Mutex , OnceCell } ;
27
- use tokio:: time:: Instant ;
28
27
use tracing:: error;
29
28
30
29
use super :: file_backed_index:: FileBackedIndex ;
31
30
use super :: store_operations:: { load_index, METASTORE_FILE_NAME } ;
32
- use super :: FileBackedIndexCell ;
31
+ use super :: { FileBackedIndexCell , FileBackedIndexWriter } ;
33
32
34
33
/// Lazy [`FileBackedIndex`]. It loads a `FileBackedIndex` on demand. When the index is first
35
34
/// loaded, it optionally spawns a task to periodically poll the storage and update the index.
36
35
pub ( crate ) struct LazyFileBackedIndex {
37
36
index_id : IndexId ,
38
37
storage : Arc < dyn Storage > ,
39
38
polling_interval_opt : Option < Duration > ,
40
- lazy_index : OnceCell < Arc < Mutex < FileBackedIndexCell > > > ,
39
+ lazy_index : OnceCell < FileBackedIndexCell > ,
41
40
}
42
41
43
42
impl LazyFileBackedIndex {
@@ -49,15 +48,15 @@ impl LazyFileBackedIndex {
49
48
file_backed_index : Option < FileBackedIndex > ,
50
49
) -> Self {
51
50
let index_mutex_opt =
52
- file_backed_index. map ( |index| Arc :: new ( Mutex :: new ( FileBackedIndexCell :: new ( index) ) ) ) ;
51
+ file_backed_index. map ( |index| FileBackedIndexCell :: new ( index) ) ;
53
52
// If the polling interval is configured and the index is already loaded,
54
53
// spawn immediately the polling task
55
54
if let Some ( index_mutex) = & index_mutex_opt {
56
55
if let Some ( polling_interval) = polling_interval_opt {
57
56
spawn_index_metadata_polling_task (
58
57
storage. clone ( ) ,
59
58
index_id. clone ( ) ,
60
- Arc :: downgrade ( index_mutex) ,
59
+ Arc :: downgrade ( & index_mutex. writer ) ,
61
60
polling_interval,
62
61
) ;
63
62
}
@@ -72,23 +71,23 @@ impl LazyFileBackedIndex {
72
71
73
72
/// Gets a synchronized `FileBackedIndex`. If the index wasn't provided on creation, we load it
74
73
/// lazily on the first call of this method.
75
- pub async fn get ( & self ) -> MetastoreResult < Arc < Mutex < FileBackedIndexCell > > > {
74
+ pub ( crate ) async fn get ( & self ) -> MetastoreResult < FileBackedIndexCell > {
76
75
self . lazy_index
77
76
. get_or_try_init ( || async move {
78
77
let index = load_index ( & * self . storage , & self . index_id ) . await ?;
79
78
let file_backed_index_cell = FileBackedIndexCell :: new ( index) ;
80
- let index_mutex = Arc :: new ( Mutex :: new ( file_backed_index_cell) ) ;
79
+ let file_backed_index_writer = Arc :: downgrade ( & file_backed_index_cell. writer ) ;
81
80
// When the index is loaded lazily, the polling task is not started in the
82
81
// constructor so we do it here when the index is actually loaded.
83
82
if let Some ( polling_interval) = self . polling_interval_opt {
84
83
spawn_index_metadata_polling_task (
85
84
self . storage . clone ( ) ,
86
85
self . index_id . clone ( ) ,
87
- Arc :: downgrade ( & index_mutex ) ,
86
+ file_backed_index_writer ,
88
87
polling_interval,
89
88
) ;
90
89
}
91
- Ok ( index_mutex )
90
+ Ok ( file_backed_index_cell )
92
91
} )
93
92
. await
94
93
. cloned ( )
@@ -98,20 +97,21 @@ impl LazyFileBackedIndex {
98
97
async fn poll_index_metadata_once (
99
98
storage : & dyn Storage ,
100
99
index_id : & str ,
101
- index_mutex : & Mutex < FileBackedIndexCell > ,
100
+ index_writer : & Mutex < FileBackedIndexWriter > ,
102
101
) {
103
- todo ! ( ) ;
104
- // FIXME
105
- /*
106
- let mut locked_index = index_mutex.lock().await;
107
- if locked_index.flip_recently_modified_down( ) {
102
+ let mut locked_index = index_writer . lock ( ) . await ;
103
+ if locked_index . upload_task . is_none ( ) {
104
+ return ;
105
+ }
106
+ if locked_index. last_push . elapsed ( ) < Duration :: from_secs ( 30 ) {
108
107
return ;
109
108
}
110
109
let load_index_result = load_index ( storage, index_id) . await ;
111
110
112
111
match load_index_result {
113
112
Ok ( index) => {
114
- *locked_index = index;
113
+ locked_index. write_state = index;
114
+ locked_index. publish ( ) ;
115
115
}
116
116
Err ( MetastoreError :: NotFound ( EntityKind :: Index { .. } ) ) => {
117
117
// The index has been deleted by the file-backed metastore holding a reference to this
@@ -127,23 +127,22 @@ async fn poll_index_metadata_once(
127
127
) ;
128
128
}
129
129
}
130
- */
131
130
}
132
131
133
132
fn spawn_index_metadata_polling_task (
134
133
storage : Arc < dyn Storage > ,
135
134
index_id : IndexId ,
136
- metastore_weak : Weak < Mutex < FileBackedIndexCell > > ,
135
+ metastore_weak : Weak < Mutex < FileBackedIndexWriter > > ,
137
136
polling_interval : Duration ,
138
137
) {
139
138
tokio:: task:: spawn ( async move {
140
139
let mut interval = tokio:: time:: interval ( polling_interval) ;
141
140
interval. set_missed_tick_behavior ( tokio:: time:: MissedTickBehavior :: Delay ) ;
142
141
interval. tick ( ) . await ; //< this is to prevent fetch right after the first population of the data.
143
142
144
- while let Some ( metadata_mutex ) = metastore_weak. upgrade ( ) {
143
+ while let Some ( metadata_writer ) = metastore_weak. upgrade ( ) {
145
144
interval. tick ( ) . await ;
146
- poll_index_metadata_once ( & * storage, & index_id, & metadata_mutex ) . await ;
145
+ poll_index_metadata_once ( & * storage, & index_id, & * metadata_writer ) . await ;
147
146
}
148
147
} ) ;
149
148
}
0 commit comments