From 488e628e690e1d3b8cd320cdaf89c218f7d350b9 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Tue, 30 Jul 2024 20:38:40 +0300 Subject: [PATCH] resolve realmMyLibrary write transaction error --- .../planet/myplanet/model/RealmMyCourse.kt | 153 +++++++++--------- .../planet/myplanet/model/RealmMyLibrary.kt | 67 ++++---- .../planet/myplanet/service/SyncManager.kt | 69 +++----- 3 files changed, 132 insertions(+), 157 deletions(-) diff --git a/app/src/main/java/org/ole/planet/myplanet/model/RealmMyCourse.kt b/app/src/main/java/org/ole/planet/myplanet/model/RealmMyCourse.kt index 66f9ff93d6..4c3638df98 100644 --- a/app/src/main/java/org/ole/planet/myplanet/model/RealmMyCourse.kt +++ b/app/src/main/java/org/ole/planet/myplanet/model/RealmMyCourse.kt @@ -89,88 +89,14 @@ open class RealmMyCourse : RealmObject() { fun insertMyCourses(userId: String?, myCousesDoc: JsonObject?, mRealm: Realm) { try { if (!mRealm.isInTransaction) { - return - } - val settings: SharedPreferences = - context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE) - val id = JsonUtils.getString("_id", myCousesDoc) - var myMyCoursesDB = - mRealm.where(RealmMyCourse::class.java).equalTo("id", id).findFirst() - if (myMyCoursesDB == null) { - myMyCoursesDB = mRealm.createObject(RealmMyCourse::class.java, id) - } - myMyCoursesDB?.setUserId(userId) - myMyCoursesDB?.courseId = JsonUtils.getString("_id", myCousesDoc) - myMyCoursesDB?.course_rev = JsonUtils.getString("_rev", myCousesDoc) - myMyCoursesDB?.languageOfInstruction = - JsonUtils.getString("languageOfInstruction", myCousesDoc) - myMyCoursesDB?.courseTitle = JsonUtils.getString("courseTitle", myCousesDoc) - myMyCoursesDB?.memberLimit = JsonUtils.getInt("memberLimit", myCousesDoc) - myMyCoursesDB?.description = JsonUtils.getString("description", myCousesDoc) - val description = JsonUtils.getString("description", myCousesDoc) - val links = extractLinks(description) - val baseUrl = Utilities.getUrl() - for (link in links) { - val concatenatedLink = "$baseUrl/$link" - concatenatedLinks.add(concatenatedLink) - } - myMyCoursesDB?.method = JsonUtils.getString("method", myCousesDoc) - myMyCoursesDB?.gradeLevel = JsonUtils.getString("gradeLevel", myCousesDoc) - myMyCoursesDB?.subjectLevel = JsonUtils.getString("subjectLevel", myCousesDoc) - myMyCoursesDB?.createdDate = JsonUtils.getLong("createdDate", myCousesDoc) - myMyCoursesDB?.setnumberOfSteps(JsonUtils.getJsonArray("steps", myCousesDoc).size()) - val courseStepsJsonArray = JsonUtils.getJsonArray("steps", myCousesDoc) - val courseStepsList = mutableListOf() - - for (i in 0 until courseStepsJsonArray.size()) { - val step_id = Base64.encodeToString( - courseStepsJsonArray[i].toString().toByteArray(), - Base64.NO_WRAP - ) - val stepJson = courseStepsJsonArray[i].asJsonObject - val step = RealmCourseStep() - step.id = step_id - step.stepTitle = JsonUtils.getString("stepTitle", stepJson) - step.description = JsonUtils.getString("description", stepJson) - val stepDescription = JsonUtils.getString("description", stepJson) - val stepLinks = extractLinks(stepDescription) - for (stepLink in stepLinks) { - val concatenatedLink = "$baseUrl/$stepLink" - concatenatedLinks.add(concatenatedLink) + mRealm.executeTransaction { realm -> + insertOrUpdateCourse(userId, myCousesDoc, realm) } - insertCourseStepsAttachments( - myMyCoursesDB?.courseId, - step_id, - JsonUtils.getJsonArray("resources", stepJson), - mRealm - ) - insertExam(stepJson, mRealm, step_id, i + 1, myMyCoursesDB?.courseId) - step.noOfResources = JsonUtils.getJsonArray("resources", stepJson).size() - step.courseId = myMyCoursesDB?.courseId - courseStepsList.add(step) + } else { + insertOrUpdateCourse(userId, myCousesDoc, mRealm) } - - myMyCoursesDB?.courseSteps = RealmList() - myMyCoursesDB?.courseSteps?.addAll(courseStepsList) - - mRealm.commitTransaction() - - val csvRow = arrayOf( - JsonUtils.getString("_id", myCousesDoc), - JsonUtils.getString("_rev", myCousesDoc), - JsonUtils.getString("languageOfInstruction", myCousesDoc), - JsonUtils.getString("courseTitle", myCousesDoc), - JsonUtils.getInt("memberLimit", myCousesDoc).toString(), - JsonUtils.getString("description", myCousesDoc), - JsonUtils.getString("method", myCousesDoc), - JsonUtils.getString("gradeLevel", myCousesDoc), - JsonUtils.getString("subjectLevel", myCousesDoc), - JsonUtils.getLong("createdDate", myCousesDoc).toString(), - JsonUtils.getJsonArray("steps", myCousesDoc).toString() - ) - courseDataList.add(csvRow) } catch (e: Exception) { - Log.e("RealmMyCourse", "Error during insertion into courses: ${e.message}") + Log.e("RealmMyCourse1", "Error during insertion into courses: ${e.message}") throw e } } @@ -194,6 +120,75 @@ open class RealmMyCourse : RealmObject() { writeCsv("${context.getExternalFilesDir(null)}/ole/course.csv", courseDataList) } + private fun insertOrUpdateCourse(userId: String?, myCousesDoc: JsonObject?, mRealm: Realm) { + val id = JsonUtils.getString("_id", myCousesDoc) + var myMyCoursesDB = mRealm.where(RealmMyCourse::class.java).equalTo("id", id).findFirst() + if (myMyCoursesDB == null) { + myMyCoursesDB = mRealm.createObject(RealmMyCourse::class.java, id) + } + myMyCoursesDB?.setUserId(userId) + myMyCoursesDB?.courseId = JsonUtils.getString("_id", myCousesDoc) + myMyCoursesDB?.course_rev = JsonUtils.getString("_rev", myCousesDoc) + myMyCoursesDB?.languageOfInstruction = JsonUtils.getString("languageOfInstruction", myCousesDoc) + myMyCoursesDB?.courseTitle = JsonUtils.getString("courseTitle", myCousesDoc) + myMyCoursesDB?.memberLimit = JsonUtils.getInt("memberLimit", myCousesDoc) + myMyCoursesDB?.description = JsonUtils.getString("description", myCousesDoc) + val description = JsonUtils.getString("description", myCousesDoc) + val links = extractLinks(description) + val baseUrl = Utilities.getUrl() + for (link in links) { + val concatenatedLink = "$baseUrl/$link" + concatenatedLinks.add(concatenatedLink) + } + myMyCoursesDB?.method = JsonUtils.getString("method", myCousesDoc) + myMyCoursesDB?.gradeLevel = JsonUtils.getString("gradeLevel", myCousesDoc) + myMyCoursesDB?.subjectLevel = JsonUtils.getString("subjectLevel", myCousesDoc) + myMyCoursesDB?.createdDate = JsonUtils.getLong("createdDate", myCousesDoc) + myMyCoursesDB?.setnumberOfSteps(JsonUtils.getJsonArray("steps", myCousesDoc).size()) + val courseStepsJsonArray = JsonUtils.getJsonArray("steps", myCousesDoc) + val courseStepsList = mutableListOf() + + for (i in 0 until courseStepsJsonArray.size()) { + val step_id = Base64.encodeToString(courseStepsJsonArray[i].toString().toByteArray(), Base64.NO_WRAP) + val stepJson = courseStepsJsonArray[i].asJsonObject + val step = RealmCourseStep() + step.id = step_id + step.stepTitle = JsonUtils.getString("stepTitle", stepJson) + step.description = JsonUtils.getString("description", stepJson) + val stepDescription = JsonUtils.getString("description", stepJson) + val stepLinks = extractLinks(stepDescription) + for (stepLink in stepLinks) { + val concatenatedLink = "$baseUrl/$stepLink" + concatenatedLinks.add(concatenatedLink) + } + insertCourseStepsAttachments(myMyCoursesDB?.courseId, step_id, JsonUtils.getJsonArray("resources", stepJson), mRealm) + insertExam(stepJson, mRealm, step_id, i + 1, myMyCoursesDB?.courseId) + step.noOfResources = JsonUtils.getJsonArray("resources", stepJson).size() + step.courseId = myMyCoursesDB?.courseId + courseStepsList.add(step) + } + + mRealm.executeTransaction { + myMyCoursesDB?.courseSteps?.clear() + myMyCoursesDB?.courseSteps?.addAll(courseStepsList) + } + + val csvRow = arrayOf( + JsonUtils.getString("_id", myCousesDoc), + JsonUtils.getString("_rev", myCousesDoc), + JsonUtils.getString("languageOfInstruction", myCousesDoc), + JsonUtils.getString("courseTitle", myCousesDoc), + JsonUtils.getInt("memberLimit", myCousesDoc).toString(), + JsonUtils.getString("description", myCousesDoc), + JsonUtils.getString("method", myCousesDoc), + JsonUtils.getString("gradeLevel", myCousesDoc), + JsonUtils.getString("subjectLevel", myCousesDoc), + JsonUtils.getLong("createdDate", myCousesDoc).toString(), + JsonUtils.getJsonArray("steps", myCousesDoc).toString() + ) + courseDataList.add(csvRow) + } + private fun extractLinks(text: String?): ArrayList { val links = ArrayList() val pattern = Pattern.compile("!\\[.*?]\\((.*?)\\)") diff --git a/app/src/main/java/org/ole/planet/myplanet/model/RealmMyLibrary.kt b/app/src/main/java/org/ole/planet/myplanet/model/RealmMyLibrary.kt index 92ade139bb..1f27f37ca9 100644 --- a/app/src/main/java/org/ole/planet/myplanet/model/RealmMyLibrary.kt +++ b/app/src/main/java/org/ole/planet/myplanet/model/RealmMyLibrary.kt @@ -14,7 +14,6 @@ import io.realm.RealmList import io.realm.RealmObject import io.realm.RealmResults import io.realm.annotations.PrimaryKey -import org.ole.planet.myplanet.MainApplication import org.ole.planet.myplanet.MainApplication.Companion.context import org.ole.planet.myplanet.utilities.Constants.PREFS_NAME import org.ole.planet.myplanet.utilities.FileUtils @@ -146,7 +145,7 @@ open class RealmMyLibrary : RealmObject() { return `object` } - fun getArray(ar: RealmList?): JsonArray { + private fun getArray(ar: RealmList?): JsonArray { val sub = JsonArray() if (ar != null) { for (s in ar) { @@ -278,7 +277,7 @@ open class RealmMyLibrary : RealmObject() { return libraries } - fun getIds(mRealm: Realm): Array { + private fun getIds(mRealm: Realm): Array { val list: List = mRealm.where(RealmMyLibrary::class.java).findAll() val ids = arrayOfNulls(list.size) for ((i, library) in list.withIndex()) { @@ -326,11 +325,11 @@ open class RealmMyLibrary : RealmObject() { `object`.addProperty("createdDate", personal.createdDate) `object`.addProperty("androidId", NetworkUtils.getUniqueIdentifier()) `object`.addProperty("deviceName", NetworkUtils.getDeviceName()) - `object`.addProperty("customDeviceName", NetworkUtils.getCustomDeviceName(MainApplication.context)) + `object`.addProperty("customDeviceName", NetworkUtils.getCustomDeviceName(context)) return `object` } - fun insertResources(doc: JsonObject, mRealm: Realm) { + private fun insertResources(doc: JsonObject, mRealm: Realm) { insertMyLibrary("", doc, mRealm) } @@ -357,13 +356,42 @@ open class RealmMyLibrary : RealmObject() { mRealm.commitTransaction() } - @JvmStatic fun insertMyLibrary(userId: String?, stepId: String?, courseId: String?, doc: JsonObject, mRealm: Realm) { - if(mRealm.isInTransaction) { - Log.e("RealmMyLibrary", "insertMyLibrary: Transaction is already in progress") - } else{ - Log.e("RealmMyLibrary", "insertMyLibrary: Transaction is not in progress") + try { + if (!mRealm.isInTransaction) { + mRealm.executeTransaction { realm -> + insertOrUpdateLibrary(userId, stepId, courseId, doc, realm) + } + } else { + insertOrUpdateLibrary(userId, stepId, courseId, doc, mRealm) + } + } catch (e: Exception) { + Log.e("RealmMyLibrary", "Error during insertion into library: ${e.message}") + throw e } + } + + fun writeCsv(filePath: String, data: List>) { + try { + val file = File(filePath) + file.parentFile?.mkdirs() + val writer = CSVWriter(FileWriter(file)) + writer.writeNext(arrayOf("libraryId", "library_rev", "title", "description", "resourceRemoteAddress", "resourceLocalAddress", "resourceOffline", "resourceId", "addedBy", "uploadDate", "createdDate", "openWith", "articleDate", "kind", "language", "author", "year", "medium", "filename", "mediaType", "resourceType", "timesRated", "averageRating", "publisher", "linkToLicense", "subject", "level", "tags", "languages", "courseId", "stepId", "downloaded", "private")) + for (row in data) { + writer.writeNext(row) + } + writer.close() + } catch (e: IOException) { + e.printStackTrace() + } + } + + fun libraryWriteCsv() { + writeCsv("${context.getExternalFilesDir(null)}/ole/library.csv", libraryDataList) + } + + @JvmStatic + fun insertOrUpdateLibrary(userId: String?, stepId: String?, courseId: String?, doc: JsonObject, mRealm: Realm) { val resourceId = JsonUtils.getString("_id", doc) val settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) var resource = mRealm.where(RealmMyLibrary::class.java).equalTo("id", resourceId).findFirst() @@ -457,25 +485,6 @@ open class RealmMyLibrary : RealmObject() { libraryDataList.add(csvRow) } - fun writeCsv(filePath: String, data: List>) { - try { - val file = File(filePath) - file.parentFile?.mkdirs() - val writer = CSVWriter(FileWriter(file)) - writer.writeNext(arrayOf("libraryId", "library_rev", "title", "description", "resourceRemoteAddress", "resourceLocalAddress", "resourceOffline", "resourceId", "addedBy", "uploadDate", "createdDate", "openWith", "articleDate", "kind", "language", "author", "year", "medium", "filename", "mediaType", "resourceType", "timesRated", "averageRating", "publisher", "linkToLicense", "subject", "level", "tags", "languages", "courseId", "stepId", "downloaded", "private")) - for (row in data) { - writer.writeNext(row) - } - writer.close() - } catch (e: IOException) { - e.printStackTrace() - } - } - - fun libraryWriteCsv() { - writeCsv("${context.getExternalFilesDir(null)}/ole/library.csv", libraryDataList) - } - @JvmStatic fun getListAsArray(db_myLibrary: RealmResults): Array { val array = arrayOfNulls(db_myLibrary.size) diff --git a/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt b/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt index 4df71afe15..b2549d9d4f 100644 --- a/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt +++ b/app/src/main/java/org/ole/planet/myplanet/service/SyncManager.kt @@ -89,7 +89,7 @@ class SyncManager private constructor(private val context: Context) { private fun startSync() { try { - val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager + val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager val wifiInfo = wifiManager.connectionInfo if (wifiInfo.supplicantState == SupplicantState.COMPLETED) { settings.edit().putString("LastWifiSSID", wifiInfo.ssid).apply() @@ -146,7 +146,6 @@ class SyncManager private constructor(private val context: Context) { } } - private fun handleException(message: String?) { if (listener != null) { isSyncing = false @@ -255,33 +254,30 @@ class SyncManager private constructor(private val context: Context) { private fun triggerInsert(stringArray: Array, resourceDoc: JsonObject) { val realm = Realm.getDefaultInstance() + var transactionStarted = false + try { - // Start transaction if not already in progress if (!realm.isInTransaction) { realm.beginTransaction() + transactionStarted = true Log.d("SyncManager", "Transaction started for ${stringArray[2]}") - } else { - Log.e("SyncManager", "Transaction already in progress for ${stringArray[2]}") - } - // Perform insertion based on category - when (stringArray[2]) { - "resources" -> insertMyLibrary(stringArray[0], resourceDoc, realm) - "meetups" -> insert(realm, resourceDoc) - "courses" -> insertMyCourses(stringArray[0], resourceDoc, realm) - "teams" -> insertMyTeams(resourceDoc, realm) - } + when (stringArray[2]) { + "resources" -> insertMyLibrary(stringArray[0], resourceDoc, realm) + "meetups" -> insert(realm, resourceDoc) + "courses" -> insertMyCourses(stringArray[0], resourceDoc, realm) + "teams" -> insertMyTeams(resourceDoc, realm) + } - // Commit transaction if it is still in progress - if (realm.isInTransaction) { - realm.commitTransaction() - Log.d("SyncManager", "Transaction committed for ${stringArray[2]}") + if (realm.isInTransaction) { + realm.commitTransaction() + Log.d("SyncManager", "Transaction committed for ${stringArray[2]}") + } } else { - Log.e("SyncManager", "No transaction in progress to commit for ${stringArray[2]}") + Log.e("SyncManager", "The Realm is already in a write transaction for ${stringArray[2]}") } } catch (e: Exception) { - // Cancel transaction if an exception occurs and transaction is in progress - if (realm.isInTransaction) { + if (transactionStarted && realm.isInTransaction) { realm.cancelTransaction() Log.e("SyncManager", "Transaction canceled for ${stringArray[2]}: ${e.message}") } @@ -291,37 +287,12 @@ class SyncManager private constructor(private val context: Context) { } saveConcatenatedLinksToPrefs() } -// private fun triggerInsert(stringArray: Array, resourceDoc: JsonObject) { -// val realm = Realm.getDefaultInstance() -// try { -// realm.executeTransaction { transactionRealm -> -// Log.d("SyncManager", "Transaction started for ${stringArray[2]}") -// -// // Perform insertion based on category -// when (stringArray[2]) { -// "resources" -> insertMyLibrary(stringArray[0], resourceDoc, transactionRealm) -// "meetups" -> insert(transactionRealm, resourceDoc) -// "courses" -> insertMyCourses(stringArray[0], resourceDoc, transactionRealm) -// "teams" -> insertMyTeams(resourceDoc, transactionRealm) -// } -// -// Log.d("SyncManager", "Transaction committed for ${stringArray[2]}") -// } -// } catch (e: Exception) { -// Log.e("SyncManager", "Error inserting into ${stringArray[2]}: ${e.message}") -// } finally { -// realm.close() -// } -// saveConcatenatedLinksToPrefs() -// } - companion object { private var ourInstance: SyncManager? = null - val instance: SyncManager? - get() { - ourInstance = SyncManager(MainApplication.context) - return ourInstance - } + val instance: SyncManager? get() { + ourInstance = SyncManager(MainApplication.context) + return ourInstance + } } } \ No newline at end of file