Comments (12)
Closing this issue bc I suspect multithreading issue on my side.
from couchbase-lite-ios.
Reopening bc current docs suggest that multithreading should not be a problem here.
from couchbase-lite-ios.
Is it possible to share the whole crash report
from couchbase-lite-ios.
Attaching lightly edited crash report - I have others that are very similar.
crash_report-2517578-8e3bd82f.txt
from couchbase-lite-ios.
If I want to try reproduce the same, could you please provide below information(preferably with similar code snippets you are using)
- what steps would you recommend?
- explain how you are using multiple threads?
- A sample document with data. (seems like there is a lot nested dictionary > array > dictionary > array >.... )
from couchbase-lite-ios.
-
what steps would you recommend?
I'm not able to reproduce this crash. The two possible causes I can think of are:- Multithreading (see below)
- Some "illegal" data that, although stored successfully, cbl is unable to retrieve.
-
explain how you are using multiple threads?
The database always gets opened on the main thread. In the four crash reports I've examined, the crash occurs when accessing the db on a different thread. -
A sample document with data. (seems like there is a lot nested dictionary > array > dictionary > array >.... )
Attached is a sample StudyHistorySet. Based on the sequence of cbl calls, I'm fairly confident that the sequence is:
toDictionary(): Document is StudyHistorySet
toArray(): Array of StudyHistory dicts
toDictionary(): StudyHistory dict
toArray(): Array of StudyHistory dicts
toDictionary(): StudyHistory dict
toArray(): Array of StudyHistory dicts
toDictionary(): StudyHistory dict
toDictionary(): TrialSeries dict
As you can see, it does contain nested dictionaries.
from couchbase-lite-ios.
Also, the crash always occurs when calling getGroupHistorySets(forContentBundle:)
. The code is:
func getGroupHistorySets(forContentBundle contentBundle: ContentBundle) -> [StudyHistorySet] {
let contentGroups = contentBundle.contentGroups
let historySets: [StudyHistorySet] = contentGroups.compactMap { fetchStorable(forDocumentType: .studyHistorySet(itemType: .group, itemId: $0.id)) }
return historySets
}
func fetchStorable<T: Storable>(forDocumentType documentType: StorableDocumentType) -> T? {
let id = documentType.id(withUserId: userId)
guard let document = database.document(withID: id) else {
return nil
}
return T.fromStorage(document.toDictionary())
}
from couchbase-lite-ios.
Will be tracking this issue here CBL-3101
from couchbase-lite-ios.
-
From the code snippet shared above, doesn't show any issue: (1) getting the document using the docID, and (2) document converted to dictionary.
The database always gets opened on the main thread. In the four crash reports I've examined, the crash occurs when accessing the db on a different thread.
If you access the database from different thread, it shouldn't have crashed. How are you accessing the db from different thread? Could you share some snippets? May be include the code snippets about the threads as well.
-
Nesting 6-7 levels also not an issue.
-
Also can you share the logic where the JSON is parsed and set into a CBLMutableDocument?
from couchbase-lite-ios.
@jayahariv Thanks for not giving up on this, much appreciated!
First, let me mention that I've released a version of my app that does all its CBL work on a dedicated thread. I have still seen one crash after making this change.
In looking again at the five crash reports I have, I noticed two things:
- This crash seems to always happen right after app launch
For example (from crash report):
Date/Time: 2021-12-01T16:48:04.999Z
Launch Time: 2021-12-01T16:47:53Z
-
It seems to happen always during the same code sequence. That sequence starts with a method that does all its work on a background queue:
let userInitiatedQueue = DispatchQueue(label: "contentBundlesViewModel.userInitiated", qos: .userInitiated)
func theMethodThatCrashes(completion: (Result) -> ()) {
userInitiatedQueue.async { [weak self] in
...
crash here
...
}
}
Inside this method, the code path always leads to an init method of another class, and inside init there's a call that hits the db.
- You asked for "the logic where the JSON is parsed and set into a CBLMutableDocument"
I guess you mean when saving docs to the db? It always goes through this method:
func createStorable<T: Storable>(from storable: T) {
let id = storable.documentType.id(withUserId: userId)
let storableDict = storable.toStorage()
let document = MutableDocument(id: id, data: storableDict)
document.setString(storable.documentType.name, forKey: Keys.documentType.rawValue)
document.setString(userId, forKey: Keys.userId.rawValue)
do {
try database.saveDocument(document)
} catch {
logger.error("Failed to create storable: \(error)")
}
}
In the crash, the objects getting retrieved are always StudyHistorySets (which contain StudyHistory objects). This is how these objects get saved:
// Converting StudyHistorySet to dict
func toStorage() -> StorableDictionary {
var stored: StorableDictionary = [
.itemId : itemId,
.itemType : itemType.rawValue,
]
if historiesByIdSet.count > 0 {
var historyKeys: [[Int]] = []
var historyValues: [StorableDictionary] = []
historiesByIdSet.forEach { entry in
historyKeys.append(Array(entry.key))
let history = entry.value
let dict = history.toStorage()
historyValues.append(dict)
}
stored[.historyKeys] = historyKeys
stored[.historyValues] = historyValues
}
return stored
}
// Converting StudyHistory to dict
func toStorage() -> StorableDictionary {
var stored: StorableDictionary = [
.itemId : itemId,
.itemType : itemType.rawValue,
.isMarkedForRemedialStudy : _isMarkedForRemedialStudy,
.isMarkedForEarlierReview : _isMarkedForEarlierReview,
.isMarkedForDelayedReview : isMarkedForDelayedReview,
.criterionTier : criterionTier.rawValue,
.numberOfTrials : numberOfTrials,
.numberOfTrialsSinceLastDueDateSet : numberOfTrialsSinceLastDueDateSet,
.numberOfSessions : numberOfSessions,
.numberOfErrors : numberOfErrors
]
addOptional(toDict: &stored, key: .dateDue, value: $dateDue.getStringValue())
addOptional(toDict: &stored, key: .trialSeries, value: trialSeries?.toStorage())
addOptional(toDict: &stored, key: .sessionSeries, value: sessionSeries?.toStorage())
let criterionScoresByTierDict = criterionScoresByTier?.mapEntries { entry in
return (entry.key.stringValue, entry.value.value) // (criterionTier, clampedValue)
}
addOptional(toDict: &stored, key: .criterionScoresByTier, value: criterionScoresByTierDict)
if let countOfConfusionsByLearnableId = self.countOfConfusionsByLearnableId {
let (countOfConfusionsKeys, countOfConfusionsValues) = countOfConfusionsByLearnableId.parallelize()
stored[.countOfConfusionsKeys] = countOfConfusionsKeys
stored[.countOfConfusionsValues] = countOfConfusionsValues
}
if childHistoryMap.count > 0 {
let values = childHistoryMap.values.map { $0.toStorage() }
stored[.childHistoryMapValues] = values
}
return stored
}
from couchbase-lite-ios.
I have a project attached, which does the similar steps mentioned, but not able to reproduce.
- Save the shared JSON via main thread.
- Read the document from userInitiated thread.
- Convert the document to dictionary via doc->toDictionary()
I can rule out:
- data issue with the attached input JSON.
- save from main thread and different thread to call doc->toDictionary()
Also the above covertion logic(StudyHistorySet/StudyHistory to dict) seems like not depended on Couchbase Lite.
from couchbase-lite-ios.
@philmitchell I will be closing the tracking Jira ticket. We can keep this GH issue open for couple more days, and if you can gather more info which helps us track down the issue. please do post info, I can open a new Jira issue.
from couchbase-lite-ios.
Related Issues (20)
- Compiling issue after upgrading to Xcode 13.2.1 HOT 1
- `ExpressionProtocol.isNotValued` and `isValued` functions are not available HOT 1
- setMapBlock is executing for all CBLView s instead of specific mentioned CBLView HOT 4
- Add Support for Combine Publishers HOT 1
- Add Linux Support HOT 5
- Add Nulls Ordering support HOT 2
- CouchbaseLite includes UIWebView, can it be changed to WKWebView? HOT 2
- Undefined symbol: _CBLVersion HOT 1
- “CouchbaseLiteSwift.framework” cannot be opened because the developer cannot be verified. HOT 3
- 【iOS Swift】CouchbaseLite Replicator ERROR: {Repl#935} Got LiteCore error: WebSocket error 1006, "connection closed abnormally" HOT 3
- Undefined symbols for CBLReplicatedDocument using CBL ObjC HOT 1
- After downloading the demo, it cannot be run. HOT 2
- Crash on `Query.removeChangeListener(withToken:)` HOT 14
- Swift Package Manager version of CouchbaseLiteSwift 3.1.3 crashes on `MutableDocument()` HOT 4
- `PrivacyInfo.xcprivacy` file is missing `NSPrivacyCollectedDataTypes` key HOT 5
- Couchbase Lite for iOS: Database Integrity Check Failures HOT 5
- Build error HOT 5
- Vector search is not available even though I installed enterprise version with pod HOT 3
- Unable to access earlier release notes HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from couchbase-lite-ios.