Coverage Summary for Class: WorkspaceInviteSyncPlugin (com.georgeci.moneysurfer.data.sync.plugin)
| Class |
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| WorkspaceInviteSyncPlugin |
100%
(3/3)
|
83.3%
(5/6)
|
100%
(28/28)
|
99.2%
(258/260)
|
| WorkspaceInviteSyncPlugin$applyDoc$1 |
|
| WorkspaceInviteSyncPlugin$push$2 |
100%
(1/1)
|
50%
(3/6)
|
100%
(10/10)
|
100%
(90/90)
|
| Total |
100%
(4/4)
|
66.7%
(8/12)
|
100%
(38/38)
|
99.4%
(348/350)
|
package com.georgeci.moneysurfer.data.sync.plugin
import co.touchlab.kermit.Logger
import com.georgeci.moneysurfer.data.db.dao.WorkspaceInviteDao
import com.georgeci.moneysurfer.data.remote.WorkspaceInviteDoc
import com.georgeci.moneysurfer.data.sync.WorkspaceDocumentWriter
import com.georgeci.moneysurfer.data.sync.toDoc
import com.georgeci.moneysurfer.data.sync.toEntity
import com.georgeci.moneysurfer.domain.AppInfo
import com.georgeci.moneysurfer.domain.logging.redactEmail
import com.georgeci.moneysurfer.domain.logging.redactUid
import com.georgeci.moneysurfer.domain.sync.SyncEntityTypes
import com.georgeci.moneysurfer.sync.api.SyncCollection
import com.georgeci.moneysurfer.sync.plugin.EntityApplyResult
import com.georgeci.moneysurfer.sync.plugin.RemoteDocument
import com.georgeci.moneysurfer.sync.plugin.SyncEntityPlugin
import com.georgeci.moneysurfer.sync.repository.ConflictMetadata
import com.georgeci.moneysurfer.sync.repository.ConflictResolver
import com.georgeci.moneysurfer.sync.repository.PendingMutation
import org.koin.core.annotation.Single
import kotlin.time.Instant
@Single(binds = [SyncEntityPlugin::class])
class WorkspaceInviteSyncPlugin(
private val writer: WorkspaceDocumentWriter,
private val appInfo: AppInfo,
private val conflictResolver: ConflictResolver,
private val workspaceInviteDao: WorkspaceInviteDao,
) : SyncEntityPlugin {
override val entityType: String = SyncEntityTypes.WORKSPACE_INVITE
override val firestoreCollectionName: String = SyncCollection.WORKSPACE_INVITES
override val pullPriority: Int = SyncPullPriorities.INVITES
private val log = Logger.withTag("WorkspaceInvitePlugin")
override suspend fun push(mutation: PendingMutation) = writer.pushToCollection(
mutation = mutation,
collectionName = SyncCollection.WORKSPACE_INVITES,
clientVersionCode = appInfo.versionCode,
strategy = WorkspaceInviteDoc.serializer(),
) { ref ->
workspaceInviteDao.getById(mutation.entityId)
?.toDoc()
?.copy(clientVersionCode = appInfo.versionCode)
?.also { dto ->
log.i {
"[push:invite] path=${ref.path} email=${dto.email.redactEmail()} " +
"status=${dto.status} role=${dto.role} " +
"target=${dto.targetUserId.redactUid()} invitedBy=${dto.invitedByUserId.redactUid()} " +
"expiresAt=${dto.expiresAt} updatedAt=${dto.updatedAt} ver=${dto.clientVersionCode}"
}
}
}
override suspend fun applyDoc(doc: RemoteDocument, scopeKey: String): EntityApplyResult {
val dto = doc.decodeOrNull(WorkspaceInviteDoc.serializer()) ?: return SKIPPED_APPLY_RESULT
if (dto.deletedAt != null) {
workspaceInviteDao.delete(doc.id)
return EntityApplyResult(applied = true, wasConflict = false)
}
val local = workspaceInviteDao.getById(doc.id)
val resolution = conflictResolver.resolve(
local = local,
remote = dto.toEntity(id = doc.id, workspaceId = scopeKey),
metadata = ConflictMetadata(
entityType = SyncEntityTypes.WORKSPACE_INVITE,
entityId = doc.id,
localUpdatedAt = local?.updatedAt?.let(Instant::fromEpochMilliseconds),
remoteUpdatedAt = Instant.fromEpochMilliseconds(dto.updatedAt),
),
)
return applyResolution(resolution) { workspaceInviteDao.upsert(it) }
}
}