Open JoakimMellonn opened 1 year ago
Hello, @JoakimMellonn and thanks for creating this issue. Are you performing a save of the new Recording
in that first line of example code? Can you also share your Amplify GraphQL schema? Thanks.
Hello, @JoakimMellonn and thanks for creating this issue. Are you performing a save of the
new Recording
in that first line of example code? Can you also share your Amplify GraphQL schema? Thanks.
I don't save the one called "recording" in Datastore, I just create it to get an ID and then copy it to put in the fileKey. I have found a workaround by saving it in Datastore before making the copy, but I don't see why this should be necessary.
The GraphQL schema for the Recording type is here (if more is needed please do let me know):
type Recording @model @auth(rules: [{allow: owner}]) {
id: ID!
name: String!
date: AWSDateTime
description: String
fileKey: String
fileName: String
fileUrl: String
speakerCount: Int!
languageCode: String
versions: [Version] @connection(keyName: "byRecording", fields: ["id"])
interviewers: [String]
labels: [String]
}
@JoakimMellonn, appreciate the clarity and you sharing your schema. It look like you could either save the new record beforehand OR just annotate the ID field with @primaryKey, which will allow you to manage it yourself.
You could then import in the uuid
library and set the id
field manually. The uuid
library comes with DataStore, so it doesn't need to be installed separately (as seen in the code example below). This way you can accomplish your intended use case with a single save.
import { v4 } from 'uuid';
const id = v4();
const key = 'recordings/' + id + '.' + fileType;
const recording = new Recording({
name: title,
description: desc,
date: new Date().toISOString(),
fileName: file.name,
fileKey: key,
speakerCount: speakerCount,
languageCode: languageCode,
});
await DataStore.save(recording);
Let me know if this helps!
Thank you, I think that I will continue to use the method mentioned with saving it. Although I still think it's weird that it just fails with a warning when trying to copy it.
An update to this issue: I've found that saving the object both before and after updating the fileKey, actually doesn't save it on the second save. It doesn't display any errors and doesn't indicate anything is wrong. But when I look in Amplify Studio at the saved recording, it misses the fileKey value.
I would appreciate it if this was looked at as a bug and not just a General question, I would personally call this, and the original way I did it, unexpected behaviour. Thank you in advance.
Agree with @JoakimMellonn , I spent an entire afternoon debugging this. In summary, the issue is "For model instance that is init locally without saving into DataStore, if run copyOf method on it, the updated instance can't be saved into DataStore anymore." @cwomack Please check whether it's a bug or limitation, for bug please fix it and for limitation please mention it in the document, thanks!
Share my case, my model name is "DailyPlan"
type DailyPlan @model @auth(rules: [{allow: owner}]) {
id: ID!
date: AWSDate!
plan: String!
}
const currentDailyPlan = new DailyPlan({ date: "2023-10-23", plan: "test" });
const updatedDailyPlan = DailyPlan.copyOf(currentDailyPlan, updated => { updated.plan = "test 2"; });
await DataStore.save(currentDailyPlan)
will success.
await DataStore.save(updatedDailyPlan)
will fail with warning message. Variable 'input' has coerced Null value for NonNull type 'AWSDate!'"
I think this pattern (creating model first use in UI, updated its content from user input, then save) is quite common for frontend development. Without supporting this pattern, developer needs to define their own model first then transform back into amplify generated models, this causes duplicate model for same data.
@cwomack would you have updates?
Updated my comments, tended we should fix this limitation.
@JoakimMellonn, after reviewing this further... I believe the issue here is that we don't support mutating a record before it's saved. You need to do a save then an update.
Is there any chance we can get steps for the reproduction of where you say "saving the object both before and after updating the fileKey, actually doesn't save it on the second save"? We'd like to see how you're doing that second save (or both saves ideally) so we can reproduce. Do you see both network requests for the 1st and 2nd save and do they look as expected? Curious to know if the version number is incrementing between the 2 requests.
@sjdeak, similar to the above comment... I think you're currently doing this: 1) new TODO (without save) 2) make several copy-of's 3) save
But I believe you'd need to change your flow to be the following: 1) new TODO (with save) 2) make several copy-of's 3) save
Can you try that change and see if that resolves the issue for you? Is there anything we're missing for your use case that doesn't make the initial save an acceptable solution?
@JoakimMellonn, after reviewing this further... I believe the issue here is that we don't support mutating a record before it's saved. You need to do a save then an update.
This is okay, but I would then request that it gets supported in the future, I personally think that it would be an intuitive thing to support, maybe that's just my opinion.
Is there any chance we can get steps for the reproduction of where you say "saving the object both before and after updating the fileKey, actually doesn't save it on the second save"? We'd like to see how you're doing that second save (or both saves ideally) so we can reproduce. Do you see both network requests for the 1st and 2nd save and do they look as expected? Curious to know if the version number is incrementing between the 2 requests.
Of course! Here is the way I'm doing it now, which actually works. But only because i query the recording before updating it and then update the queried recording, instead of the one I just saved.
const recording = new Recording({
name: title,
description: desc,
date: new Date().toISOString(),
fileName: file.name,
fileKey: '',
speakerCount: speakerCount,
languageCode: languageCode
});
try {
await DataStore.save(recording);
} catch (err) {
console.error(`Error while saving recording first time: ${err}`);
}
...
try {
const key = 'recordings/' + recording.id + '.' + fileType;
const uploadedRecording = (await DataStore.query(Recording, (r) => r.id.eq(recording.id)))[0]; // without getting the recording to then copy it, it doesn't work.
const updatedRecording = Recording.copyOf(uploadedRecording, copy => {
copy.fileKey = key
});
...
Hi @JoakimMellonn 👋 just wanted to follow up and see where we're at.
It sounds like you are able to successfully create and update records but I'd like to confirm that you are unblocked after the guidance provided.
If so, I can convert this issue to a feature request for the ability to mutate a record before it's been saved to the local store.
Hi @JoakimMellonn 👋 just wanted to follow up and see where we're at.
It sounds like you are able to successfully create and update records but I'd like to confirm that you are unblocked after the guidance provided.
If so, I can convert this issue to a feature request for the ability to mutate a record before it's been saved to the local store.
Hi sorry for the late reply. I can confirm that I'm currently unblocked by this, and thank you.
Before opening, please confirm:
JavaScript Framework
Angular
Amplify APIs
DataStore
Amplify Categories
api
Environment information
Describe the bug
I'm getting this warning when saving a Datastore object, after using obj.copyOf() to update one value on the object. I don't know when, but it stopped working some time ago, and I haven't been able to find a workaround or a fix, so this exact code has worked earlier. And what I think the weird thing is, is the fact that the "newRecording" changes from when I console.log it to when I save it in Datastore.
Expected behavior
The object should be updated accordingly and saved to Datastore without warning.
Reproduction steps
Code Snippet
Log output
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
No response