@@ -189,7 +189,7 @@ export class Loki extends LokiEventEmitter {
189189 }
190190 }
191191
192- this . autosaveDisable ( ) ;
192+ this . _autosaveDisable ( ) ;
193193
194194 // if they want to load database on loki instantiation, now is a good time to load... after adapter set and before
195195 // possible autosave initiation
@@ -202,7 +202,7 @@ export class Loki extends LokiEventEmitter {
202202
203203 return loaded . then ( ( ) => {
204204 if ( this . _autosave ) {
205- this . autosaveEnable ( ) ;
205+ this . _autosaveEnable ( ) ;
206206 }
207207 } ) ;
208208 }
@@ -734,13 +734,9 @@ export class Loki extends LokiEventEmitter {
734734 // for autosave scenarios, we will let close perform final save (if dirty)
735735 // For web use, you might call from window.onbeforeunload to shutdown database, saving pending changes
736736 if ( this . _autosave ) {
737- this . autosaveDisable ( ) ;
738- // Check if collections are dirty.
739- for ( let idx = 0 ; idx < this . _collections . length ; idx ++ ) {
740- if ( this . _collections [ idx ] . dirty ) {
741- saved = this . saveDatabase ( ) ;
742- break ;
743- }
737+ this . _autosaveDisable ( ) ;
738+ if ( this . _autosaveDirty ( ) ) {
739+ saved = this . saveDatabase ( ) ;
744740 }
745741 }
746742
@@ -929,25 +925,24 @@ export class Loki extends LokiEventEmitter {
929925 return Promise . reject ( new Error ( "persistenceAdapter not configured" ) ) ;
930926 }
931927
932- let saved ;
933-
934928 // check if the adapter is requesting (and supports) a 'reference' mode export
935929 if ( this . _persistenceAdapter . mode === "reference" && typeof this . _persistenceAdapter . exportDatabase === "function" ) {
936930 // filename may seem redundant but loadDatabase will need to expect this same filename
937- saved = this . _persistenceAdapter . exportDatabase ( this . filename , this . copy ( { removeNonSerializable : true } ) ) ;
938- }
939- // otherwise just pass the serialized database to adapter
940- else {
941- saved = this . _persistenceAdapter . saveDatabase ( this . filename , this . serialize ( ) as string ) ;
931+ return Promise . resolve ( this . _persistenceAdapter . exportDatabase ( this . filename , this . copy ( { removeNonSerializable : true } ) ) )
932+ . then ( ( ) => {
933+ this . _autosaveClearFlags ( ) ;
934+ this . emit ( "save" ) ;
935+ } ) ;
942936 }
943937
944- return Promise . resolve ( saved ) . then ( ( ) => {
945- // Set all collection not dirty.
946- for ( let idx = 0 ; idx < this . _collections . length ; idx ++ ) {
947- this . _collections [ idx ] . dirty = false ;
948- }
949- this . emit ( "save" ) ;
950- } ) ;
938+ // otherwise just pass the serialized database to adapter
939+ // persistenceAdapter might be asynchronous, so we must clear `dirty` immediately
940+ // or autosave won't work if an update occurs between here and the callback
941+ this . _autosaveClearFlags ( ) ;
942+ return Promise . resolve ( this . _persistenceAdapter . saveDatabase ( this . filename , this . serialize ( ) as string ) )
943+ . then ( ( ) => {
944+ this . emit ( "save" ) ;
945+ } ) ;
951946 }
952947
953948 /**
@@ -959,7 +954,7 @@ export class Loki extends LokiEventEmitter {
959954 *
960955 * @returns {Promise } a Promise that resolves after the database is persisted
961956 */
962- saveDatabase ( ) {
957+ public saveDatabase ( ) {
963958 if ( ! this . _throttledSaves ) {
964959 return this . _saveDatabase ( ) ;
965960 }
@@ -989,7 +984,7 @@ export class Loki extends LokiEventEmitter {
989984 *
990985 * @returns {Promise } a Promise that resolves after the database is deleted
991986 */
992- deleteDatabase ( ) {
987+ public deleteDatabase ( ) {
993988 // the persistenceAdapter should be present if all is ok, but check to be sure.
994989 if ( this . _persistenceAdapter === null ) {
995990 return Promise . reject ( new Error ( "persistenceAdapter not configured" ) ) ;
@@ -998,10 +993,32 @@ export class Loki extends LokiEventEmitter {
998993 return Promise . resolve ( this . _persistenceAdapter . deleteDatabase ( this . filename ) ) ;
999994 }
1000995
996+ /**
997+ * Check whether any collections are "dirty" meaning we need to save the (entire) database
998+ * @returns {boolean } - true if database has changed since last autosave, otherwise false
999+ */
1000+ private _autosaveDirty ( ) : boolean {
1001+ for ( let idx = 0 ; idx < this . _collections . length ; idx ++ ) {
1002+ if ( this . _collections [ idx ] . dirty ) {
1003+ return true ;
1004+ }
1005+ }
1006+ return false ;
1007+ }
1008+
1009+ /**
1010+ * Resets dirty flags on all collections.
1011+ */
1012+ private _autosaveClearFlags ( ) {
1013+ for ( let idx = 0 ; idx < this . _collections . length ; idx ++ ) {
1014+ this . _collections [ idx ] . dirty = false ;
1015+ }
1016+ }
1017+
10011018 /**
10021019 * Starts periodically saves to the underlying storage adapter.
10031020 */
1004- autosaveEnable ( ) {
1021+ private _autosaveEnable ( ) : void {
10051022 if ( this . _autosaveHandle ) {
10061023 return ;
10071024 }
@@ -1024,7 +1041,7 @@ export class Loki extends LokiEventEmitter {
10241041 /**
10251042 * Stops the autosave interval timer.
10261043 */
1027- autosaveDisable ( ) {
1044+ private _autosaveDisable ( ) : void {
10281045 this . _autosave = false ;
10291046
10301047 if ( this . _autosaveHandle ) {
0 commit comments