From 2302bddd0591f363082e5263523365ddb85be838 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 | 58 ++++--- .../planet/myplanet/service/SyncManager.kt | 66 +++----- 3 files changed, 129 insertions(+), 148 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 fcf87e9048..2d57c14c72 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 @@ -82,90 +82,20 @@ open class RealmMyCourse : RealmObject() { companion object { private val gson = Gson() private val concatenatedLinks = ArrayList() - val courseDataList: MutableList> = mutableListOf() + private val courseDataList: MutableList> = mutableListOf() @JvmStatic - fun insertMyCourses(userId: String?, myCoursesDoc: JsonObject?, mRealm: Realm) { + fun insertMyCourses(userId: String?, myCousesDoc: JsonObject?, mRealm: Realm) { try { if (!mRealm.isInTransaction) { - Log.e("RealmMyCourse", "insertMyCourses: Transaction is not in progress") - return - } else { - Log.e("RealmMyCourse", "insertMyCourses: Transaction is already in progress") - } - val settings: SharedPreferences = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE) - val id = JsonUtils.getString("_id", myCoursesDoc) - 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", myCoursesDoc) - myMyCoursesDB?.courseRev = JsonUtils.getString("_rev", myCoursesDoc) - myMyCoursesDB?.languageOfInstruction = - JsonUtils.getString("languageOfInstruction", myCoursesDoc) - myMyCoursesDB?.courseTitle = JsonUtils.getString("courseTitle", myCoursesDoc) - myMyCoursesDB?.memberLimit = JsonUtils.getInt("memberLimit", myCoursesDoc) - myMyCoursesDB?.description = JsonUtils.getString("description", myCoursesDoc) - val description = JsonUtils.getString("description", myCoursesDoc) - val links = extractLinks(description) - val baseUrl = Utilities.getUrl() - for (link in links) { - val concatenatedLink = "$baseUrl/$link" - concatenatedLinks.add(concatenatedLink) - } - myMyCoursesDB?.method = JsonUtils.getString("method", myCoursesDoc) - myMyCoursesDB?.gradeLevel = JsonUtils.getString("gradeLevel", myCoursesDoc) - myMyCoursesDB?.subjectLevel = JsonUtils.getString("subjectLevel", myCoursesDoc) - myMyCoursesDB?.createdDate = JsonUtils.getLong("createdDate", myCoursesDoc) - myMyCoursesDB?.numberOfSteps = JsonUtils.getJsonArray("steps", myCoursesDoc).size() - val courseStepsJsonArray = JsonUtils.getJsonArray("steps", myCoursesDoc) - 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", myCoursesDoc), - JsonUtils.getString("_rev", myCoursesDoc), - JsonUtils.getString("languageOfInstruction", myCoursesDoc), - JsonUtils.getString("courseTitle", myCoursesDoc), - JsonUtils.getInt("memberLimit", myCoursesDoc).toString(), - JsonUtils.getString("description", myCoursesDoc), - JsonUtils.getString("method", myCoursesDoc), - JsonUtils.getString("gradeLevel", myCoursesDoc), - JsonUtils.getString("subjectLevel", myCoursesDoc), - JsonUtils.getLong("createdDate", myCoursesDoc).toString(), - JsonUtils.getJsonArray("steps", myCoursesDoc).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 } } @@ -189,6 +119,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?.courseRev = 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 c5d8888e32..65c2341580 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 @@ -352,13 +352,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() @@ -452,25 +481,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 listToString(list: RealmList?): String { val s = StringBuilder() 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 77cd8d17ff..9d228dfcd7 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 @@ -254,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}") } @@ -290,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