在日程安排应用程序中为用户实施预订锁定

implement a booking lock for users in a scheduling app

我构建了一个日程安排网络应用程序,用户可以在该应用程序中为给定的日期和时间段预订会议。

现在我需要实现一个预订锁,这意味着管理员可以应用这个锁,用户从那时起就不能再预订了。

我当前的设计包括一个模型 booking_lock,它只有一个 "status" 属性,值为 "On" 和 "Off"。

该模型在任何给定时间在数据库中只有一个记录,因为它唯一的责任是提供数据以检查预订是否已被锁定。

--------------------编辑------------------------ ------------

这并不是要锁定个别记录(会议)。为此,我使用了 user_id 的属性。如果为 0,则会议可以预订。

我现在要做的是在用户访问数据库之前完全禁用(锁定)预订。

例如:

当用户登录时,他们会看到一条通知,说明预订已锁定。此外,他们不会看到相应的按钮来预订会议,如果他们偶然导航到相应的 URL,他们将被重定向到主页,并显示与上述相同的通知。这些我都搞定了。

但我需要一个通用开关来打开和关闭,作为这种检查的基础。因此 booking_lock 模型。

注:我用的是hanami-model.

--------------------编辑------------------------ ------------

我的问题是双重的:

  1. 有没有更好的方法来实现这样的锁?
  2. 如何确保这种锁在数据库中只有一条记录?

您可以尝试 ActiveRecord pessimistic locking 方法或类似方法。在您的记录上设置一个指示锁定的字段并尝试:

booking_lock = UUID.new # Or any sufficiently unique string
Booking.update_all({ id: @booking.id, booking_lock: booking_lock }, { booking_lock: nil })
booked = Booking.find_by(id: @booking.id, booking_lock: booking_lock)

如果您取回记录,则您已成功锁定它。如果不是,您需要使用不同的预订再试一次,它在您领取之前就被抢走了。

1。有没有更好的方法来实现这样的锁?

您的要求似乎是应用程序范围的设置,最好使用

  • 一个环境变量
  • 存储在数据库中的值

环境变量:

  • 优点:系统已经到位,使用简单,可以轻松静态配置和动态更改
  • 缺点:多租户架构可能难以维护(多个服务器 运行 同一个应用程序)

数据库持久化

  • 优点:使用多租户架构轻松扩展
  • 缺点:对于一种设置来说似乎有点矫枉过正,但可以很容易地抽象到一个 Key/Value 存储中用于多种设置。

示例:

创建一个包含两列的 AppSettings 模型:键和值。

使用键“lock_booking_for_parents”创建并保存 AppSetting,并通过管理界面更改值。

在整个应用程序中访问此 AppSetting 以了解您是否应该锁定预订。

此外,如果您担心每次需要知道预订是否 enabled/disabled 时都要查询数据库,您可以轻松实现缓存。

2。如何确保这种锁在数据库中只有一条记录?

环境变量

不适用

数据库持久化

您可以创建一个帮助程序 class 以使用默认行为访问您的设置,并使用 first_or_create 方法确保记录是唯一的。

class AppSettingsHelper

    def self.booking_enable?
      app_setting_record = AppSettings.find_by_key("lock_booking_for_parents")
      if app_setting_record 
        return app_setting_record.value
      else 
        ## default behavior of your app when no record has been created yet
        return true
      end
    end
    
    def self.enable_booking
      AppSettings.where(:key => "lock_booking_for_parents").first_or_create({value: false})
    end
    
    def self.disable_booking
      AppSettings.where(:key => "lock_booking_for_parents").first_or_create({value: true})
    end  
end