Skip to content
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

Upgrading to v12 causes duplicate to be created instead of updated when updating nested object #6517

Closed
mattlewer opened this issue Feb 28, 2024 · 14 comments
Assignees
Labels
Encryption:Off Frequency:Always More-information-needed More information is needed to progress. The issue will close automatically in 2 weeks. O-Community Repro:Always SDK-Use:Local T-Bug

Comments

@mattlewer
Copy link

mattlewer commented Feb 28, 2024

How frequently does the bug occur?

Always

Description

Similar issues:
#6322
#6239

We have been using Realm v11.10.1 without issues, since upgrading to v12.6.0, we are encountering errors updating nested objects.

We receive an updated version of an object from our server in JSON format.
We want to update the Realm object in the devices local database so that the changes are reflected.

The object we have looks like this, with each name being its own Realm table:

Session: {
    User: {
        Organisations: []
    }
}

We update the object in Realm like so:

  const update = (updates: () => void) => {
    realm.write(() => {
      updates();
    });
  };

and call this function as such:

update(() => {
    session.user = updatedUser;
});

We receive this error:
Attempting to create an object of type 'User' with an existing primary key value '341'

In an attempt to fix this, we have adapted the update function to be the following, this also works on v11.10.1 without issue:

const update = (original: T, changes: Partial<T>) => {
    realm.write(() => {
      realm.create(
        'session',
        merge({}, original, changes),
        Realm.UpdateMode.Modified,
      );
    });
};

Which is then called as such:

update(session, {
          user: updatedUser,
});

This also fails, however giving an error a layer deeper:
Error: Attempting to create an object of type 'Organisation' with an existing primary key value '454'

Stacktrace & log output

No response

Can you reproduce the bug?

Always

Reproduction Steps

Have an object stored in Realm
Attempt to update this objects nested fields, using an interfaced JSON object, containing the primary key
Receive error

Version

12.6.0

What services are you using?

Local Database only

Are you using encryption?

No

Platform OS and version(s)

Android & iOS

Build environment

Which debugger for React Native: ..

Cocoapods version

No response

Copy link

sync-by-unito bot commented Feb 28, 2024

➤ PM Bot commented:

Jira ticket: RJS-2744

@kneth
Copy link
Contributor

kneth commented Mar 1, 2024

@mattlewer Thank you for reporting. Is it possible for you to share the schema?

@sync-by-unito sync-by-unito bot added the Waiting-For-Reporter Waiting for more information from the reporter before we can proceed label Mar 1, 2024
@mattlewer
Copy link
Author

mattlewer commented Mar 1, 2024

@mattlewer Thank you for reporting. Is it possible for you to share the schema?

Hopefully this helps

Config

export const config: Realm.Configuration = {
  schema: [
    OrganisationRealm,
    Session,
    User,
  ],
  schemaVersion: 4,
};
export default createRealmContext(config);

Session

import {Realm} from '@realm/react';
import User from './User';
import idGenerator from '../../services/idGenerator';

export default class Session extends Realm.Object {
  client_id!: string;
  user!: User;

  static create(user: User): Object {
    return {
      user: user,
    };
  }

  static schema = {
    name: 'Session',
    primaryKey: 'client_id',
    properties: {
      client_id: {type: 'string', default: () => idGenerator.generate()},
      user: 'User',
    },
  };
}

User

import 'react-native-get-random-values';
import {Realm} from '@realm/react';
import idGenerator from '../../services/idGenerator';
import {Organisation} from './Organisation';

export default class User extends Realm.Object {
  client_id!: string;
  id!: number;
  inviting_organisations?: Organisation[];

  static schema = {
    name: 'User',
    primaryKey: 'id',
    properties: {
      client_id: {type: 'string', default: () => idGenerator.generate()},
      id: 'int',
      inviting_organisations: 'Organisation[]',
    },
  };
}

Organisation

import 'react-native-get-random-values';
import {Realm} from '@realm/react';
import idGenerator from '../../services/idGenerator';

export interface Organisation extends Syncable {
  client_id: string;
  id: number;
  name: string;
  created_at: Date;
  updated_at: Date;
}

export class OrganisationRealm extends Realm.Object implements Organisation {
  client_id!: string;
  id!: number;
  name!: string;
  created_at!: Date;
  updated_at!: Date;
  resource!: string;

  static schema = {
    name: 'Organisation',
    primaryKey: 'id',
    properties: {
      client_id: {type: 'string', default: () => idGenerator.generate()},
      id: 'int',
      name: 'string',
      created_at: {type: 'date', default: () => new Date()},
      updated_at: {type: 'date', default: () => new Date()},
      resource: {type: 'string', default: SyncResource.Organisations},
    },
  };
}

Syncable

export interface Syncable {
  id?: number;
  client_id?: string;
  created_at: Date;
  updated_at: Date;
  is_synced?: boolean;
  resource?: string;
}

SyncResource

 export enum SyncResource { Organisations = 'organisations', }

idGenerator

const idGenerator = () => {
  const generate = (): string => {
    return new Realm.Types.UUID().toHexString(true);
  };

  return {
    generate,
  };
};

export default idGenerator();

@github-actions github-actions bot added Needs-Attention Reporter has responded. Review comment. and removed Waiting-For-Reporter Waiting for more information from the reporter before we can proceed labels Mar 1, 2024
@kneth
Copy link
Contributor

kneth commented Mar 6, 2024

It sounds like the same as #6129 and we released a fix for it in v12.2.0.

@sync-by-unito sync-by-unito bot added Waiting-For-Reporter Waiting for more information from the reporter before we can proceed and removed Needs-Attention Reporter has responded. Review comment. labels Mar 6, 2024
@mattlewer
Copy link
Author

Has this potentially regressed since as I'm using v12.6.0? Will downgrade to v12.2.0 to see if it makes a difference and get back to you

@github-actions github-actions bot added Needs-Attention Reporter has responded. Review comment. and removed Waiting-For-Reporter Waiting for more information from the reporter before we can proceed labels Mar 6, 2024
@kneth
Copy link
Contributor

kneth commented Mar 6, 2024

downgrade to v12.2.0 to see if it makes a difference

Thanks!

@sync-by-unito sync-by-unito bot added Waiting-For-Reporter Waiting for more information from the reporter before we can proceed and removed Needs-Attention Reporter has responded. Review comment. labels Mar 6, 2024
@mattlewer
Copy link
Author

mattlewer commented Mar 6, 2024

Same error:

Original update function:
Error: Attempting to create an object of type 'User' with an existing primary key value '341'

Adapted update function:
Error: Attempting to create an object of type 'Organisation' with an existing primary key value '454'.

@github-actions github-actions bot added Needs-Attention Reporter has responded. Review comment. and removed Waiting-For-Reporter Waiting for more information from the reporter before we can proceed labels Mar 6, 2024
@nirinchev
Copy link
Member

So the first error is expected:

realm.write(() => {
	session.user = updatedUser;
});

where updatedUser is an unmanaged object will attempt to first add it to realm and then set session.user to it. In the case where the user already exists, you're supposed to get an error.

The second code snippet points to a legitimate bug though, however I've been unable to reproduce it. I've attached my attempt to repro this - if you can modify it in a way that triggers the duplicate PK error, let us know and we'll continue investigating.

Archive.zip

@sync-by-unito sync-by-unito bot added More-information-needed More information is needed to progress. The issue will close automatically in 2 weeks. and removed Needs-Attention Reporter has responded. Review comment. labels Mar 20, 2024
@mattlewer
Copy link
Author

mattlewer commented Mar 26, 2024

Thank you for getting back to me, I will have a look ASAP.

Given the above situation, what would be the correct way to update this nested object? I would assume that because it comes down with the same primary key as the object currently stored in the DB, it would successfully match these up and update it, I don't quite understand why it would cause an error?

Also as this worked fine in v11, is there something specific that has caused this breaking change? If I downgrade again, everything works as intended.

@github-actions github-actions bot removed the More-information-needed More information is needed to progress. The issue will close automatically in 2 weeks. label Mar 26, 2024
@nirinchev
Copy link
Member

Did

update(() => {
    session.user = updatedUser;
});

work with v11? If it did, it's definitely unintended and likely a bug with v11. The other code snippet - i.e.:

realm.write(() => {
      realm.create(
        'session',
        merge({}, original, changes),
        Realm.UpdateMode.Modified,
      );
    });

Should work in both v11 and v12 and is the right way to do it. If it doesn't work with v12, then we should definitely fix it, but I can't repro it so far.

@mattlewer
Copy link
Author

Yep, both worked fine with v11, will try and reproduce with a test when I have a moment and get back to you

@sync-by-unito sync-by-unito bot added the More-information-needed More information is needed to progress. The issue will close automatically in 2 weeks. label Apr 10, 2024
Copy link
Contributor

This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.

@kneth kneth reopened this Apr 30, 2024
@kneth
Copy link
Contributor

kneth commented Apr 30, 2024

@mattlewer

will try and reproduce with a test when I have a moment and get back to you

Any chance you have a moment to create a reproduction case for us?

Copy link
Contributor

github-actions bot commented May 1, 2024

This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further.

@github-actions github-actions bot closed this as completed May 1, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 31, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Encryption:Off Frequency:Always More-information-needed More information is needed to progress. The issue will close automatically in 2 weeks. O-Community Repro:Always SDK-Use:Local T-Bug
Projects
None yet
Development

No branches or pull requests

3 participants