Managing plans in a collaborative setting can be challenging, especially when multiple team members are simultaneously editing the same plan. This can result in conflicting changes, versioning issues, and ultimately, delays. When we faced this kind of problem at our organization, we decided to tackle it head-on. In this article, we will share our experience of developing a solution that would enable simultaneous plan editing in a multi-user environment. We will discuss the challenges we encountered, our approach to solving them, and the lessons we learned along the way. By the end of this article, you will have a better understanding of the strategies and tools that can be used to manage simultaneous editing in your own projects.
In the Product Department, we specialize in providing high-quality plugins for the Atlassian marketplace. With over five years of experience in the industry, the department has established itself as a reliable and trusted provider of plugins for a wide range of Atlassian products. Its portfolio includes several popular plugins that are used by customers worldwide, and the team is committed to continuously improving its offerings to meet the evolving needs of the Atlassian community. The department takes pride in delivering innovative and effective solutions that help customers optimize their workflows and achieve their business goals.
While searching for ways to make our plugin stand out from others, and better answer the needs of users, we came up with the idea of adding a simultaneous editing feature. One of our colleagues, as part of their learning, familiarized themselves with the topic and implemented a proof of concept. We tested this proof of concept by implementing two actions in our plugin and found it promising. As a result, we decided to integrate it into our plugin.
Previously, when a user accessed a plan, they would send a request to the socket.io server to log in to the virtual room. Subsequent users who accessed the same plan were also added to the virtual room. Any changes made to the plan, such as adding a user or assigning a task to a user, were sent to the socket.io server and then broadcasted to other users in the same virtual room.
We have placed a strong emphasis on ensuring high performance of our solution. As part of this effort, we have taken steps to minimize the amount of information that is transmitted. Only the essential information required for making changes is included in the requests, allowing us to maximize the efficiency of our system. Initially, this implementation had limitations, and sometimes users attempted to make conflicting changes to the same task, resulting in inconsistent data.
As a response to this issue, we collaborated with our Innovative Solutions and Excellence team, and devised a solution. We modified the socket server to behave like a plan editor, enabling it to store the current state of the plan and update it with every change event from editors. This modification ensures that the socket server always has an up-to-date version of the plan, allowing us to detect conflicts and resolve them efficiently. In other words, the socket server became the primary source of information about the state of the plan.
With this solution implemented, if two editors attempted to make different changes to the same task, the socket server would detect a conflict. The first change that the server processed would be accepted, while the second change could not be processed because the server detected that the previous state did not match the current state of the plan. In response, the editor would receive the current state of the plan from the server.
We operate within the ecosystem of Atlassian products. Therefore, it was crucial for us to meet the high-security standards that Atlassian sets for external solutions. As such, ensuring data security was one of our key requirements during implementation. On the frontend, we used full objects with sensitive data such as Plan and Task. However, when communicating with the socket server, we only needed the object identifiers: userId, taskId, and planId (PlanDTO, TaskDTO).
To implement conflict resolution, we needed the same functions that were called on the frontend when the user made changes to the plan. The only difference was that the frontend application worked with full objects, while we only had DTO objects on the socket server.
Initially, we did not have access to these functions, as our infrastructure consisted of three separate applications: frontend, backend (Java), and socket server (NodeJS + Express + Socket.io). To avoid duplicating the code, we changed the project infrastructure and implemented a monorepo for the frontend application.
Now, our frontend consists of two parts: the React application and the socket server, with shared code. We also improved the existing code by adding missing information to some actions, such as the previous state of the task, which was necessary for detecting conflicts.
As a team, we tested the solution using several different approaches. The goal was to identify any potential issues and improve the solution before release. We used the following three testing methods:
- Testing with precise steps – in this approach, we tried to simulate conflicts and issues by outlining each step that team members needed to take.
- Testing through play – we gave team members three minutes to perform any actions on the platform.
- Testing with a scenario – each team member was given a specific goal to achieve using the platform. This allowed us to see how team members approached different tasks, and helped us to improve the overall user experience.
Altogether, the testing went very well, and we were able to catch and fix minor bugs. As of February 14th, the solution is available for use with the Team Planner – Resource Planning for Jira app, and we are confident that it will provide a better user experience for our customers.
Our challenge was to improve our plugin by adding simultaneous editing functionality. To address this issue, we collaborated with our Innovative Solutions and Excellence team and came up with a solution. We modified the socket server to behave like a plan editor, storing the current state of the plan and updating it with every change event from editors. With this improvement, users can now carry out their planning activities in a more engaging, transparent, and efficient manner.
Read more about Team Planner and its features.