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

Immutability FTW #19

Open
andywer opened this issue Aug 30, 2017 · 0 comments
Open

Immutability FTW #19

andywer opened this issue Aug 30, 2017 · 0 comments

Comments

@andywer
Copy link

andywer commented Aug 30, 2017

A subtle issue you can find in most ORMs today is that you mutate model instances as you go and sync them with the remote database from time to time. It seems like an easy and convenient approach, but falls short if a model instance is used concurrently (esp. dangerous in JS with async code everywhere!).

Consider this:

const user = await User.findByName('Karl')
await Promise.all([
  renameUser(user, 'John'),
  changeBirthday(user, '1990-08-01')
])

async function renameUser (user, newName) {
  await something()
  user.name = newName
}

async function changeBirthday (user, birthday) {
  await somethingElse()
  user.birthday = birthday
  console.log(`User ${user.name}'s birthday is the ${birthday}.`)
  // Race Condition! Maybe `user.name` is still 'Karl', maybe it is already 'John'!
}

You can easily spend an hour of debugging to recognize the issue. And fixing it may be even harder.
So I'd like to propose a different approach:

const user = await User.findByName('Karl')
await renameUser(user, 'John')

async function renameUser (user, newName) {
  await something()
  // Returns an updated user instance, the old instance remains untouched
  user = user.setName(newName)
}

The setter methods could probably be easily derived from the field name. You could also track the change operations (setName, setBirthday, ...) since the last database sync and have a change history. Might be nice for debugging and to only update fields in the database that have actually changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants