Repository navigation
Reduce Firestore reads from survey sync and survey list #3984
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
a7655dc
8802dfd
419fbb4
72fb678
8fb685e
9cdd426
9be1ccf
93ed06c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,9 +18,9 @@ package org.groundplatform.android.data.remote.firebase.schema | |
|
|
||
| import com.google.firebase.firestore.CollectionReference | ||
| import com.google.firebase.firestore.FieldPath | ||
| import com.google.firebase.firestore.snapshots | ||
| import kotlinx.coroutines.flow.Flow | ||
| import kotlinx.coroutines.flow.map | ||
| import kotlinx.coroutines.flow.flow | ||
| import kotlinx.coroutines.tasks.await | ||
| import org.groundplatform.android.data.remote.firebase.base.FluentCollectionReference | ||
| import org.groundplatform.android.proto.Role | ||
| import org.groundplatform.android.proto.Survey as SurveyProto | ||
|
|
@@ -39,27 +39,38 @@ class SurveysCollectionReference internal constructor(ref: CollectionReference) | |
|
|
||
| fun survey(id: String) = SurveyDocumentReference(reference().document(id)) | ||
|
|
||
| /** | ||
| * Emits the surveys readable by [user] once per collection. Deliberately a one-shot read rather | ||
| * than a realtime listener, which bills every document again on each reconnect. | ||
| */ | ||
| fun getReadable(user: User): Flow<List<Survey>> { | ||
| val references = | ||
| reference() | ||
| .whereIn(STATE, ALLOWED_STATES) | ||
| .whereIn(FieldPath.of(ACL_FIELD, user.email), ALLOWED_ROLES) | ||
|
|
||
| return references.snapshots().map { snapshot -> | ||
| snapshot.documents | ||
| .mapNotNull { SurveyConverter.toSurvey(it) } | ||
| .filter { survey -> | ||
| survey.generalAccess == Survey.GeneralAccess.GENERAL_ACCESS_UNSPECIFIED || | ||
| survey.generalAccess == Survey.GeneralAccess.RESTRICTED || | ||
| survey.generalAccess == Survey.GeneralAccess.UNLISTED | ||
| } | ||
| return flow { | ||
| val snapshot = references.get().await() | ||
| val surveys = | ||
| snapshot.documents | ||
| .mapNotNull { SurveyConverter.toSurvey(it) } | ||
| .filter { survey -> | ||
| survey.generalAccess == Survey.GeneralAccess.GENERAL_ACCESS_UNSPECIFIED || | ||
| survey.generalAccess == Survey.GeneralAccess.RESTRICTED || | ||
| survey.generalAccess == Survey.GeneralAccess.UNLISTED | ||
| } | ||
| emit(surveys) | ||
| } | ||
|
rfontanarosa marked this conversation as resolved.
Resolved
Comment on lines
+52
to
63
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Switching from |
||
| } | ||
|
rfontanarosa marked this conversation as resolved.
Resolved
|
||
|
|
||
| fun getPublicReadable(): Flow<List<Survey>> = | ||
| reference() | ||
| .whereEqualTo(GENERAL_ACCESS_FIELD, SurveyProto.GeneralAccess.PUBLIC_VALUE) | ||
| .whereIn(STATE, listOf(SurveyProto.State.READY_VALUE)) | ||
| .snapshots() | ||
| .map { snapshot -> snapshot.documents.mapNotNull(SurveyConverter::toSurvey) } | ||
| /** Emits the public surveys once per collection. See [getReadable]. */ | ||
| fun getPublicReadable(): Flow<List<Survey>> = flow { | ||
| val snapshot = | ||
| reference() | ||
| .whereEqualTo(GENERAL_ACCESS_FIELD, SurveyProto.GeneralAccess.PUBLIC_VALUE) | ||
| .whereIn(STATE, listOf(SurveyProto.State.READY_VALUE)) | ||
| .get() | ||
| .await() | ||
| emit(snapshot.documents.mapNotNull(SurveyConverter::toSurvey)) | ||
| } | ||
|
rfontanarosa marked this conversation as resolved.
Resolved
rfontanarosa marked this conversation as resolved.
Resolved
rfontanarosa marked this conversation as resolved.
Resolved
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,8 +52,10 @@ class SurveySyncService @Inject constructor(private val workManager: WorkManager | |
| companion object { | ||
| /** | ||
| * How long to wait before syncing. A single change often triggers several updates in quick | ||
| * succession, and each run re-reads the whole survey, so it is cheaper to let them settle. | ||
| * succession, and each run re-reads the whole survey, so it is cheaper to let them settle. Kept | ||
| * long to bound Firestore reads when many data collectors share a survey, as every change | ||
| * notifies each of their devices. | ||
| */ | ||
| private const val SYNC_DELAY_MILLIS = 10_000L | ||
| private const val SYNC_DELAY_MILLIS = 30 * 60 * 1000L | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A static delay of 30 minutes ( |
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.