防止用户在同一行上工作

时间:2021-06-09 15:21:11

I have a web application at work that is similar to a ticket working system. Some users enter new issues. Other workers choose and resolve issues. All of the data is maintained in MS SQL server 2005.

我有一个工作中的web应用程序,它类似于票据工作系统。一些用户输入新问题。其他员工选择并解决问题。所有数据都在MS SQL server 2005中维护。

The users working to resolve issues go to a page where they can view open issues. Because up to twenty people can be looking at this page at the same time, one potential problem I had to address was what happens if someone picks an issue that someone else picked just after their page loaded.

致力于解决问题的用户访问一个可以查看开放问题的页面。因为多达20个人可以同时看这个页面,我必须解决的一个潜在问题是,如果有人在他们的页面加载之后选择了另一个问题,会发生什么。

To address this, I did two things. First, the gridview displaying the issues to select uses an AJAX timer to update every second. Once an issue has been selected, it disappears one second later at most. In case they select one within this second, they get a message asking them to choose another.

为了解决这个问题,我做了两件事。首先,显示要选择的问题的gridview使用AJAX计时器每秒钟更新一次。一旦一个问题被选中,它就会在一秒之后消失。如果他们在这一秒内选择了一个,他们会收到一条信息,要求他们选择另一个。

The problem is that the AJAX part of this is sending too many updates (this is what I am assuming) and it is affecting the performance of the page and database. In addition, the updates are not performing every second. I find the timer to be unreliable when working to trigger stored procedures.

问题是,AJAX部分发送了太多的更新(这是我所假设的),它影响了页面和数据库的性能。此外,更新并不是每一秒都在执行。在触发存储过程时,我发现计时器不可靠。

There has to be a better way, but I can't seem to find one. Does anyone have experience with a situation like this or have suggestions to keep multiple users from selecting the same record to maintain? I really do not want to disable the AJAX part entirely because I feel the message alone would make the application frustrating to use.

必须有更好的办法,但我似乎找不到。有人有过类似的经历吗?或者有建议阻止多个用户选择要维护的相同记录?我真的不想完全禁用AJAX部分,因为我觉得仅使用消息就会使应用程序难以使用。

Thanks,

谢谢,

6 个解决方案

#1


3  

Two things can help mitigate your problem.

有两件事可以帮助你缓解问题。

First, after-selection notification that the case has been taken is needed regardless of your ajax update time frame. Even checking every second doesn't mean two people cannot click the same case at what they perceive to be the same time. In such cases, one of the users needs to be notified that their selection is invalid even though it appeared valid when selected. This notification doesn't need to be elaborate; keeping a light, helpful tone can improve user perception even in the light of disappointment. And if you identify the user who selected that record already, that will not only help your users coordinate in future but also divert attention from your program to the user who snaked the juicy case. (indeed, management may like giving your users the occasional collision as it will motivate them to select cases faster)

首先,无论您的ajax更新时间框架如何,都需要进行选择后的通知。即使每一秒钟都要检查,也并不意味着两个人不能在他们认为相同的时间点击同一个案例。在这种情况下,需要通知其中一个用户他们的选择是无效的,即使它在选择时看起来是有效的。此通知无需详细说明;即使是在失望的情况下,保持轻松、有帮助的语气也能提高用户的感知能力。如果您确定已经选择该记录的用户,这不仅将帮助您的用户在未来进行协调,而且还将注意力从您的程序转移到跟踪这个有趣案例的用户。(实际上,管理人员可能喜欢给用户偶尔的冲突,因为这会促使他们更快地选择案例)

Second, a small tweak to how you display your cases can reduce selection collisions. Adding a random element to display order and/or filtering out every other case on display will help your users select different cases naturally. Human pattern recognition and task selection isn't really random so small changes to presentation can equal big changes to selection behavior. Reductions in collision chance keeps your collision notifications rare (and thus less frustrating to your users). This is even better if your users can be separated into classifications that can help determine useful case ordering/filtering.

其次,稍微调整一下显示案例的方式可以减少选择冲突。添加一个随机元素来显示订单和/或过滤掉所有其他的情况,将帮助您的用户自然选择不同的案例。人类模式识别和任务选择并不是随机的,所以对表现的微小改变就等于对选择行为的巨大改变。减少碰撞的机会使您的碰撞通知很少(因此对您的用户来说不那么令人沮丧)。如果您的用户可以被划分为可以帮助确定有用的案例排序/过滤的分类,这就更好了。

Okay, a third thing that will help you over time is if you keep a log of when collisions occur (with helpful meta data about the collision—like who was involved and selection timing). Armed with solid collision data, you can find what works and what doesn't. Over time, you can hone your application to your actual use cases as well as identify potential problems early. Nothing reassures your users more than being on top of a problem (and able to explain your plans to solve it) before they're even aware it exists.

好的,第三件事将帮助你随着时间的推移,如果你保持一个碰撞发生时的日志(有关于碰撞的有用的元数据,像谁参与和选择时间)。有了坚实的碰撞数据,你就能发现哪些有效,哪些无效。随着时间的推移,您可以将应用程序磨练到实际的用例中,并尽早发现潜在的问题。没有什么比在用户意识到问题存在之前就解决问题(并且能够解释解决问题的计划)更能让他们安心的了。

With these mitigating patterns, you'll probably find you can safely reduce your ajax query timeframe without affecting user experience. And with useful logging, you'll have the assurance that any tweaks you put in place are actually working (or not—which is maybe even more useful to know).

有了这些缓和模式,您可能会发现您可以安全地减少ajax查询时间,而不会影响用户体验。有了有用的日志记录,您就可以确保您所做的任何调整实际上都是有效的(或者不是)——这可能更有用。

#2


4  

Put a lock timestamp field on the row in the database. Write a stored proc that returns true or false if the expiration timsetamp is older than a specific time. Set your sessions on your web app to expire in the same time, a minute or two. When a user select a row they hit the stored proc which helps the app to decide if it should let the user to modify it.

在数据库中的行上放置一个锁时间戳字段。编写一个存储的proc,如果过期时间timsetamp大于特定时间,则返回true或false。设置web应用程序上的会话在同一时间(一两分钟)过期。当用户选择一行时,他们会点击存储的proc,这有助于应用程序决定是否应该让用户修改它。

Hope that makes sense....

希望有意义....

#3


3  

I did something similar where once a user opened a ticket (row) it assigned that ticket to that user and set a value on that record, like and FK to that particular user, so if anyone else tried to open that ticket (row) it would let them know it has already been assigned to someone else.

我做了类似的事情,一旦用户打开一张票(行)分配门票,用户并设置一个值,记录,像颗特定用户,如果任何人试图打开票(行)将让他们知道它已经分配给其他人。

#4


2  

If possible limit the system so that they just get the next open issue off the work queue as opposed having them be able choose from all open issues.

如果可能的话,限制系统,使他们从工作队列中获得下一个开放问题,而不是让他们能够从所有开放问题中进行选择。

If that isn't possible, I suppose you could check upon the choosing of an issue to see if it is still available. If it's not available, then make it disappear after the user clicks on it. This way you are only requesting when they actually click on something as opposed to constant polling of the data.

如果这是不可能的,我想你可以检查一下问题的选择,看看它是否仍然可用。如果它没有可用,则在用户单击它之后使它消失。通过这种方式,您只在他们实际单击某样东西时发出请求,而不是对数据进行持续的轮询。

#5


2  

Have you tried increasing the time between refreshes. I would expect that once per 30 seconds would be sufficient. 40 requests/minute is a lot less load than 1200/minute. Your users may not even notice the difference.

你试过增加休息时间吗?我希望每30秒一次就足够了。每分钟40个请求比每分钟1200个请求要少得多。您的用户可能甚至没有注意到差异。

If they do, how about providing a refresh button on the page so the users can manually refresh the list just prior to selecting an item to avoid the annoying message if they choose.

如果有,在页面上提供一个refresh按钮,以便用户可以在选择项之前手动刷新列表,以避免他们选择的烦人消息。

#6


1  

I'm missing to see the issue, specially after you mentioned you are already flagging tickets as in progress/being maintained and have a timestamp/version of the item.

我没有看到这个问题,特别是在你提到你已经在退票的情况下,正在维护,并且有一个时间戳/版本的项目。

Isn't the following enough:

不够以下:

  1. User browses the tickets and sees a list of available tickets i.e. this excludes ones that are in the db as in progress. If you want the users to also see tickets in progress, you indicate it clearly in the ticket status and disable the option to take it.
  2. 用户浏览球票并看到可用球票的列表,也就是说,这就排除了db中正在进行的球票。如果您想让用户也看到正在进行中的票据,您可以在票据状态中明确地指出它,并禁用接受它的选项。
  3. User either flags a ticket as in progress explicitly or implicitly by opening the ticket (depends on the user experience / how its presented to the users).
  4. 用户可以显式地标记正在进行的票据,也可以通过打开票据隐式地标记票据(取决于用户体验/它如何呈现给用户)。
  5. User explicitly moves the ticket to a different status i.e. completed, invalid, awaiting for feedback, etc.
  6. 用户显式地将票移动到不同的状态,如已完成、无效、等待反馈等。

When the items are retrieved at 1, you include a timestamp/version. When 2 happens, you use a optimistic concurrency approach to make sure that if 2 persons try to update the take the ticket at the same time only the first one will be successful.

当项在1处被检索时,您将包含一个时间戳/版本。当出现2时,您使用乐观并发方法来确保如果2个人试图同时更新take the ticket,那么只有第一个将成功。

What will happen is that for the second person, the update ... where ... timestamp = @timestamp will not find any records to update and you will report back that the ticket was already taken.

对于第二个人来说,更新将会发生……在那里……timestamp = @timestamp将不会发现任何需要更新的记录,您将报告该票已经被拿走。

If you want, you can build on top of the above to update the UI as tickets are grabbed. This could be by just doing a full refresh of the current page of tickets after x time (maybe alerting/prompting the user), or even by retrieving a list of tickets changed for the page of tickets being showed with ajax. You still have the earlier steps in place, as this modification its just a convenience for the users.

如果需要,可以在上面的基础上构建,以便在获取票证时更新UI。这可以通过在x时间之后对当前的票务页面进行一次完整的刷新(可能是提醒/提示用户),甚至可以通过检索ajax显示的票务页面中更改的票务列表来实现。您仍然有前面的步骤,因为这个修改对用户来说只是一个方便。

#1


3  

Two things can help mitigate your problem.

有两件事可以帮助你缓解问题。

First, after-selection notification that the case has been taken is needed regardless of your ajax update time frame. Even checking every second doesn't mean two people cannot click the same case at what they perceive to be the same time. In such cases, one of the users needs to be notified that their selection is invalid even though it appeared valid when selected. This notification doesn't need to be elaborate; keeping a light, helpful tone can improve user perception even in the light of disappointment. And if you identify the user who selected that record already, that will not only help your users coordinate in future but also divert attention from your program to the user who snaked the juicy case. (indeed, management may like giving your users the occasional collision as it will motivate them to select cases faster)

首先,无论您的ajax更新时间框架如何,都需要进行选择后的通知。即使每一秒钟都要检查,也并不意味着两个人不能在他们认为相同的时间点击同一个案例。在这种情况下,需要通知其中一个用户他们的选择是无效的,即使它在选择时看起来是有效的。此通知无需详细说明;即使是在失望的情况下,保持轻松、有帮助的语气也能提高用户的感知能力。如果您确定已经选择该记录的用户,这不仅将帮助您的用户在未来进行协调,而且还将注意力从您的程序转移到跟踪这个有趣案例的用户。(实际上,管理人员可能喜欢给用户偶尔的冲突,因为这会促使他们更快地选择案例)

Second, a small tweak to how you display your cases can reduce selection collisions. Adding a random element to display order and/or filtering out every other case on display will help your users select different cases naturally. Human pattern recognition and task selection isn't really random so small changes to presentation can equal big changes to selection behavior. Reductions in collision chance keeps your collision notifications rare (and thus less frustrating to your users). This is even better if your users can be separated into classifications that can help determine useful case ordering/filtering.

其次,稍微调整一下显示案例的方式可以减少选择冲突。添加一个随机元素来显示订单和/或过滤掉所有其他的情况,将帮助您的用户自然选择不同的案例。人类模式识别和任务选择并不是随机的,所以对表现的微小改变就等于对选择行为的巨大改变。减少碰撞的机会使您的碰撞通知很少(因此对您的用户来说不那么令人沮丧)。如果您的用户可以被划分为可以帮助确定有用的案例排序/过滤的分类,这就更好了。

Okay, a third thing that will help you over time is if you keep a log of when collisions occur (with helpful meta data about the collision—like who was involved and selection timing). Armed with solid collision data, you can find what works and what doesn't. Over time, you can hone your application to your actual use cases as well as identify potential problems early. Nothing reassures your users more than being on top of a problem (and able to explain your plans to solve it) before they're even aware it exists.

好的,第三件事将帮助你随着时间的推移,如果你保持一个碰撞发生时的日志(有关于碰撞的有用的元数据,像谁参与和选择时间)。有了坚实的碰撞数据,你就能发现哪些有效,哪些无效。随着时间的推移,您可以将应用程序磨练到实际的用例中,并尽早发现潜在的问题。没有什么比在用户意识到问题存在之前就解决问题(并且能够解释解决问题的计划)更能让他们安心的了。

With these mitigating patterns, you'll probably find you can safely reduce your ajax query timeframe without affecting user experience. And with useful logging, you'll have the assurance that any tweaks you put in place are actually working (or not—which is maybe even more useful to know).

有了这些缓和模式,您可能会发现您可以安全地减少ajax查询时间,而不会影响用户体验。有了有用的日志记录,您就可以确保您所做的任何调整实际上都是有效的(或者不是)——这可能更有用。

#2


4  

Put a lock timestamp field on the row in the database. Write a stored proc that returns true or false if the expiration timsetamp is older than a specific time. Set your sessions on your web app to expire in the same time, a minute or two. When a user select a row they hit the stored proc which helps the app to decide if it should let the user to modify it.

在数据库中的行上放置一个锁时间戳字段。编写一个存储的proc,如果过期时间timsetamp大于特定时间,则返回true或false。设置web应用程序上的会话在同一时间(一两分钟)过期。当用户选择一行时,他们会点击存储的proc,这有助于应用程序决定是否应该让用户修改它。

Hope that makes sense....

希望有意义....

#3


3  

I did something similar where once a user opened a ticket (row) it assigned that ticket to that user and set a value on that record, like and FK to that particular user, so if anyone else tried to open that ticket (row) it would let them know it has already been assigned to someone else.

我做了类似的事情,一旦用户打开一张票(行)分配门票,用户并设置一个值,记录,像颗特定用户,如果任何人试图打开票(行)将让他们知道它已经分配给其他人。

#4


2  

If possible limit the system so that they just get the next open issue off the work queue as opposed having them be able choose from all open issues.

如果可能的话,限制系统,使他们从工作队列中获得下一个开放问题,而不是让他们能够从所有开放问题中进行选择。

If that isn't possible, I suppose you could check upon the choosing of an issue to see if it is still available. If it's not available, then make it disappear after the user clicks on it. This way you are only requesting when they actually click on something as opposed to constant polling of the data.

如果这是不可能的,我想你可以检查一下问题的选择,看看它是否仍然可用。如果它没有可用,则在用户单击它之后使它消失。通过这种方式,您只在他们实际单击某样东西时发出请求,而不是对数据进行持续的轮询。

#5


2  

Have you tried increasing the time between refreshes. I would expect that once per 30 seconds would be sufficient. 40 requests/minute is a lot less load than 1200/minute. Your users may not even notice the difference.

你试过增加休息时间吗?我希望每30秒一次就足够了。每分钟40个请求比每分钟1200个请求要少得多。您的用户可能甚至没有注意到差异。

If they do, how about providing a refresh button on the page so the users can manually refresh the list just prior to selecting an item to avoid the annoying message if they choose.

如果有,在页面上提供一个refresh按钮,以便用户可以在选择项之前手动刷新列表,以避免他们选择的烦人消息。

#6


1  

I'm missing to see the issue, specially after you mentioned you are already flagging tickets as in progress/being maintained and have a timestamp/version of the item.

我没有看到这个问题,特别是在你提到你已经在退票的情况下,正在维护,并且有一个时间戳/版本的项目。

Isn't the following enough:

不够以下:

  1. User browses the tickets and sees a list of available tickets i.e. this excludes ones that are in the db as in progress. If you want the users to also see tickets in progress, you indicate it clearly in the ticket status and disable the option to take it.
  2. 用户浏览球票并看到可用球票的列表,也就是说,这就排除了db中正在进行的球票。如果您想让用户也看到正在进行中的票据,您可以在票据状态中明确地指出它,并禁用接受它的选项。
  3. User either flags a ticket as in progress explicitly or implicitly by opening the ticket (depends on the user experience / how its presented to the users).
  4. 用户可以显式地标记正在进行的票据,也可以通过打开票据隐式地标记票据(取决于用户体验/它如何呈现给用户)。
  5. User explicitly moves the ticket to a different status i.e. completed, invalid, awaiting for feedback, etc.
  6. 用户显式地将票移动到不同的状态,如已完成、无效、等待反馈等。

When the items are retrieved at 1, you include a timestamp/version. When 2 happens, you use a optimistic concurrency approach to make sure that if 2 persons try to update the take the ticket at the same time only the first one will be successful.

当项在1处被检索时,您将包含一个时间戳/版本。当出现2时,您使用乐观并发方法来确保如果2个人试图同时更新take the ticket,那么只有第一个将成功。

What will happen is that for the second person, the update ... where ... timestamp = @timestamp will not find any records to update and you will report back that the ticket was already taken.

对于第二个人来说,更新将会发生……在那里……timestamp = @timestamp将不会发现任何需要更新的记录,您将报告该票已经被拿走。

If you want, you can build on top of the above to update the UI as tickets are grabbed. This could be by just doing a full refresh of the current page of tickets after x time (maybe alerting/prompting the user), or even by retrieving a list of tickets changed for the page of tickets being showed with ajax. You still have the earlier steps in place, as this modification its just a convenience for the users.

如果需要,可以在上面的基础上构建,以便在获取票证时更新UI。这可以通过在x时间之后对当前的票务页面进行一次完整的刷新(可能是提醒/提示用户),甚至可以通过检索ajax显示的票务页面中更改的票务列表来实现。您仍然有前面的步骤,因为这个修改对用户来说只是一个方便。