-
-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ParseInstallation does not store object ID in key-value store #115
Comments
I'm assuming you are using ParseSwift on Linux/Android? This is very possible, currently looking into the problem... |
No, tested on iOS and macCatalyst this time. I'll check if #116 addresses the issue |
Makes sense. When I found what the issue was it showed up across all OSs. |
I also see this issue. Happy to see a fix is already in the works. |
Sure, as soon as one of you confirms it works I will merge |
I'm not sure if the behavior improved. Tested the following (branch "current"): save the Installation on app start
|
@jt9897253 Can you post your actual error and your whole |
Install struct:
This should be enough to reproduce the issue (parse server running locally in Docker):
Full error:
|
I've added an auto migration/deletion that will ask for a new installation if the objectId for the current installation isn't saved to the Keychain, so you shouldn't need to do anything else but update the SDK. |
This was tested on iOS simulator. I just deleted the app, everything from _Installation on the server and the issue is still present on second start.
I think I tried that, but was not allowed (got an error message like "you are not allow to query _Installation"). |
I think I see the issue, I'll let you know when I have an update |
Also, as said above, I tried fetching the current installation with
but this did not work, presumably as the installation's object id is nil when fetching. |
I just made a commit that should fix the issue |
I've added an auto migration/deletion that will ask for a new installation if the objectId for the current installation isn't saved to the Keychain, so you shouldn't need to do anything else but update the SDK. |
Still not working here. In the Installation playground file, running save twice does work. I can reproduce this in the app: when saving the installation two times after one another, I do not get an error. If I then stop the app and run it again, I see the Is the in memory store working correctly but when persisting to disk using a custom key-value store (called |
Can you post how you are saving? It's easier to see what's going on when you post what you are doing and the "complete" errors you are getting.
I'm not sure what you mean. Are you asking me if your custom key value store is working correctly? You will need to post the code for it for me to determine that |
Using the following code:
Results in the following output the first time the app is started:
Results in the following output the second time the app is started:
myStore (of type MyStorage) is simply persisting to user defaults:
|
You shouldn't be saving like this, these are two asynchronous calls, there's a high probability they will clash. You need to either switch them to synchronous calls or use below (playgrounds does it because you are suppose to complete each line step-by-step): if let serverURL = URL(string: "http://localhost:1337/parse") {
ParseSwift.initialize(applicationId: "APPLICATION_ID", clientKey: "CLIENT_KEY", serverURL: serverURL, keyValueStore: myStore)
AppInstallInfo.current?.save { (result: Result<AppInstallInfo, ParseError>) in
switch result {
case .success(_):
print("successfully saved installation on server")
AppInstallInfo.current?.save { (result: Result<AppInstallInfo, ParseError>) in
switch result {
case .success(_):
print("successfully saved installation on server")
case .failure(let error):
print("failed to save installation on server: \(error)")
}
}
case .failure(let error):
print("failed to save installation on server: \(error)")
}
}
} else {
print("invalid parse server url")
} Can you report after you make the fix above. The other issues you mentioned are most likely dependent on how you were saving. |
When performing the asynchronous network calls sequentially the output is as follows. First run of app:
Second run of app:
Error message is shown once as the second save is only performed on success of the first save. Thus, I do not think this is related to concurrency. |
What happens when you don't use your store. Initializing without it? |
When using if let serverURL = URL(string: "http://localhost:1337/parse") {
ParseSwift.initialize(applicationId: "APPLICATION_ID", clientKey: "CLIENT_KEY", serverURL: serverURL, keyValueStore: nil)
AppInstallInfo.current?.save { (result: Result<AppInstallInfo, ParseError>) in
switch result {
case .success(_):
print("successfully saved installation on server")
AppInstallInfo.current?.save { (result: Result<AppInstallInfo, ParseError>) in
switch result {
case .success(_):
print("successfully saved installation on server")
case .failure(let error):
print("failed to save installation on server: \(error)")
}
}
case .failure(let error):
print("failed to save installation on server: \(error)")
}
}
} else {
print("invalid parse server url")
} Output for first run of app:
Output for the second run of app:
|
I'm not able to replicate your problem. I've tried in my own app and in playgrounds: //Async
Installation.current?.save {
print($0)
Installation.current?.save {
print($0)
}
} //Sync
try? Installation.current?.save()
try? Installation.current?.save() Both work fine for me along with playgrounds. Where are you initializing the Parse SDK? I also mention #93 (comment) about not saving the installation right after initialization. You can see the next comment for the reasons for why it's not needed in most cases #93 (comment). If you really want to initialize there you can try a "dispatch after a second or 2" to see if it helps. This thread will close once the PR is merged. If you want to try to create a test case in the test files that recreate your use-case and open back the issue, feel free |
@funkenstrahlen can you let us know if this works for you? |
Sure, will try this in the next days and provide feedback. |
I use ParseSwift |
Thank you for your work and time @cbaker6 ❤️ |
@funkenstrahlen thanks for your feedback! I made sure to test out Installation.fetch on a server in an attempt to cover corner cases and it seems to work fine now that the 1st |
I am currently only testing in the simulator and completely erased the simulator storage after upgrading to 1.3.0. Therefore all installations I tested are created in a fresh state and I can not comment if the upgrade process works as expected. |
I did not change anything else than removing the additional dispatch after logout before accessing installation. As mentioned before I completely erased my existing state in the simulator for a fresh start after that. |
Just tested again with release 1.3.0 and I think |
I’m glad it’s working for you! One note about your custom key/value store, I suggest you use the Parse JSON encoder/decoder as Parse has a custom date strategy the stock encoder doesn’t account for. Besides the date strategy, it’s the stock encoder. This can end up causing unexpected behavior or even worse it won’t decode your objects from the store (you can use any of your ParseObjects to get encoder or decoder) https://github.com/netreconlab/ParseCareKit/blob/e893ce0830239b06986fffce9ee97aa2c5d83e3a/Sources/ParseCareKit/ParseCareKitUtility.swift#L73-L81 You can see info about these in the docs: http://parseplatform.org/Parse-Swift/api/Protocols/ParseObject.html#/s:10ParseSwift0A6ObjectPAAE14getJSONEncoder10Foundation0E0CyF let us know if find any other issues! |
Assume a struct
MyParseInstallation
conforming toParseInstallation
.If I understand the code correctly, calling
MyParseInstallation.current?.save { (result: Result<AppInstallInfo, ParseError>) in [...] }
intends to persist the ParseInstallation data to the server.However, calling
MyParseInstallation.current?.fetch(completion: { (result: Result<AppInstallInfo, ParseError>) in [...]}
always returns a failure.Problem seems to be that
objectId
ofMyParseInstallation
is not persisted to theParseKeyValueStore
. Thus, the fetch returnsParseError(code: ParseSwift.ParseError.Code.unknownError, message: "Cannot fetch an object without id")
Another effect of not storing
objectId
in the key-value store is that multiple calls toMyParseInstallation.current?.save
result in multiple ParseInstallation objects being created on the server, all with the same data but different ids.Tested on both the latest release and the
removeDispatch
branch.The text was updated successfully, but these errors were encountered: