Skip to content

KennethMathari/DataSyncEngine

Repository files navigation

Pula Sync Engine

A robust, offline-first Survey Response Sync Engine built for Kotlin Multiplatform (Android & iOS). This library is designed for field agents operating in rural areas with unreliable connectivity, ensuring survey data is captured locally and synced efficiently when a network becomes available.

Features

  • Offline-First Storage: Uses Room KMP for reliable local persistence.
  • Resilient Sync Logic: Handles partial failures (only retries failed items) and detects network degradation (stops early to save battery).
  • Concurrency Protection: Thread-safe sync process using Mutex to prevent duplicate uploads.
  • Structured Data Model: Supports complex, nested, and repeating survey sections (e.g., multiple farms per farmer) using a type-safe SurveyContent hierarchy and Room TypeConverters.
  • Platform Agnostic: Shared business logic for Android and iOS.

Getting Started

Prerequisites

  • JDK 17+
  • Android Studio / IntelliJ IDEA
  • Kotlin 2.2.20+
  • KSP (Kotlin Symbol Processing)

Cloning the Repository

git clone https://github.com/KennethMathari/DataSyncEngine.git
cd DataSyncEngine

Publishing to Local Maven Repository

To use this library in your own project, publish it to your local Maven cache:

# Clean and publish all Android and iOS targets to ~/.m2/repository
./gradlew clean :library:publishToMavenLocal -Dkotlin.compiler.execution.strategy="in-process"

Note: GPG signing is disabled for local publishing to simplify the development workflow.


Library Integration

1. Configure Repositories

In your consuming project's settings.gradle.kts (or root build.gradle.kts), add mavenLocal():

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        mavenLocal() // Required to find DataSyncEngine
    }
}

2. Add Dependency

Add the library to your shared module's build.gradle.kts:

kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("com.pula.sync:library:1.0.0")
        }
    }
}

Usage Example

A. Implement Domain Abstractions

Define how your app interacts with the network and your specific backend.

import com.pula.sync.engine.SyncApi
import com.pula.sync.engine.NetworkMonitor
import com.pula.sync.data.SurveyResponse
import com.pula.sync.engine.NetworkException

// Check for actual connectivity (e.g., via ConnectivityManager)
class MyNetworkMonitor : NetworkMonitor {
    override fun isConnected(): Boolean = true 
}

// Handle the actual network call to your server
class MyBackendApi : SyncApi {
    override suspend fun upload(response: SurveyResponse): Result<String> {
        return try {
            // httpClient.post(...) 
            Result.success("server_id_123")
        } catch (e: Exception) {
            Result.failure(NetworkException("Network timeout"))
        }
    }
}

B. Initialize and Sync

import com.pula.sync.data.getDatabaseBuilder
import com.pula.sync.engine.SyncManager
import com.pula.sync.data.SurveyResponse
import com.pula.sync.data.SurveyContent
import com.pula.sync.data.SurveyStatus
import kotlinx.datetime.Clock

class SurveyRepository(context: Any?) {
    // 1. Initialize Database (pass Context on Android, null on iOS)
    private val database = getDatabaseBuilder(context).build()
    
    // 2. Initialize Manager
    private val syncManager = SyncManager(
        dao = database.surveyDao(),
        api = MyBackendApi(),
        networkMonitor = MyNetworkMonitor()
    )

    // 3. Capture survey offline
    suspend fun saveSurvey(id: String, content: SurveyContent) {
        val response = SurveyResponse(
            id = id,
            content = content,
            attachments = emptyList(),
            status = SurveyStatus.PENDING,
            createdAt = Clock.System.now().toEpochMilliseconds()
        )
        database.surveyDao().insert(response)
    }

    // 4. Trigger Sync (Background or Manual)
    suspend fun startSync() {
        val completed = syncManager.sync()
        if (completed) println("Sync finished!")
    }
}

Architecture & Design

For detailed architectural decisions, including media handling, GPS validation, and remote troubleshooting strategies, see ARCHITECTURE.md.

Testing

Run the cross-platform test suite:

./gradlew :library:allTests

License

Licensed under the Apache License, Version 2.0.

About

A robust, offline-first Survey Response Sync Engine built for Kotlin Multiplatform (Android & iOS). This library is designed for field agents operating in rural areas with unreliable connectivity, ensuring survey data is captured locally and synced efficiently when a network becomes available.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages