37

There's a project I'm working on that is looking to produce a web application that will manage a task list between multiple users. This is a master task list whose task items get distributed by an authorized user. Each user has his/her own account to login and view the tasks they are assigned; it is possible for multiple users to have a single task in-common.

I am trying to leave details of the project out of this as I'm grappling more with the overall concept of how to handle the following situations, but if it helps, I'm using Java, EclipseLink, and GWT with RequestFactory implemented. The database is PostgreSQL.

So the conceptual problems I am attempting to reconcile are the following:

  1. If a single task that is common to multiple users changes in any way e.g. task completed, deleted, etc., the task list of all the users who have this task will be updated. What design patterns are there that assist in implementing this function?

    • Some patterns I have looked at are Observer and Mediator - are there others that should be considered over these?
  2. Say there are two users changing the same task at the same time.

    • First, should I allow that situation to happen or should I put a lock on it until one or the other person is done making changes?

    • Second, if I don't put a lock on it, how do I reconcile whose changes to accept? This involves the situation in 1 because user 1 could submit the data and before user 2 receives the updated data, he/she may have gone ahead and submitted his/her's changes.

I am really looking for any guiding points, advice, or tips you can provide on how to properly sync data between multiple instances of this web app. I would very much appreciate it!

4 Answers 4

28

I think Whiteboard will be your pattern of choice for #1, you should post changes to tasks (or other shared data) in a common place, so all interested parties can see them and DTRT.

For #2, you need to look at optimistic locking. Basically, you need to timestamp all your editable records with the last update time. When you try to save the record, you first verify that the record in the database has the same last-updated timestamp as your record. If not, then someone has updated the record and you now have to either get the updated record and inform the user that they need to enter their changes again, or you can try to merge the user's changes into the updated record (which usually turns out to be either simple or impossible).

1
  • up for 'last-updated timestamp' :) nice one!
    – Padi
    Feb 1, 2021 at 15:09
9

I came up with a design for a desktop application (that has yet to be fully tested) with similar requirements that might be helpful.

My solution was to employ the MVC pattern (with a single Model but multiple Controllers and Views) where each Controller made changes to the Model using transactions (using STM) and when a transaction committed, the Model broadcasted an update notification to the View(s).

Each client also all kept track of anything being updated locally, but when those local updates were finished (i.e. sent to be committed) it reverted to using the underlying Model's info.

I also had an undo stack with all the changes the users made so that things could be reverted.

This might not be the best model for a web app though since the Model had to broadcast changes to the Views, which might not be the easiest w/ a web client.

4

for 1. you should see if the publish/subscribe pattern is better suited.
for 2. it depends on your situation:

  • how frequent will this situation be?
  • how bad is a situation in which one of your users will be unable to update a task because it is locked or someone else has changed it in the meantime?
    personally I prefer an approach (used e.g. in pivotaltracker) in which there are:
    • no locks,
    • you see all changes in real-time, and
    • the UI invites doing frequent minor updates instead of bigger ones on multiple attributes.
    • you keep a history of all changes that have been made. if the history is visible to the users, eventually arising conflicts or overwrites can be resolved with comments, annotations or messages.
2
  • The question is more academic, so I will say very frequent to look at how it's taken care of in the worst-case. +1 for the pattern references. Jan 18, 2013 at 13:41
  • @kr1 pivotaltracker lacks conflict warning and does not merge non conflicting changes, so it should not be used a a good example of a good record editing multiuser application.
    – Eduardo
    Jul 15, 2019 at 15:01
1

My recommendation is to never lock and report a conflict if it happens.

Please, take a look at:

https://github.com/spring-projects/spring-petclinic/issues/433

You can see a video and sample code.

Will that meet your requirements?

Not the answer you're looking for? Browse other questions tagged or ask your own question.