我需要在视频编码时将编码状态值存储
我有一个视频对象。在对视频进行编码时,需要锁定其评论的编辑内容。
因此,视频需要存储其当前的编码状态(是/否发生?)并允许子注释查询该属性。
请注意
我知道有更好的方法来解决这个特殊问题。我实际上需要解决一个稍微不同的问题,但我觉得它的细微差别会使问题混淆,所以我选择了这个问题。我的问题是关于isntance变量的细微差别而不是如何更好地解决这个编码问题(显然需要一个队列)。
class Video
has_many :comments
after_initialize do
@encoding_in_process = false
end
def encode
@encoding_in_process = true
...
@encoding_in_process = false
end
def encoding_in_process?
@encoding_in_process
end
end
class Comment
belongs_to :video
before_update
raise "locked" if video.encoding_in_process?
end
...
end
如您所见,每个视频实例都存储一个实例变量@encoding_in_process
,用于确定是否可以更新注释。
问题
同一个视频的多个内存中实例存在危险,每个实例都有@encoding_in_process
的不同值。
e.g。
bieber_video = Video.find_all_by_artist('Bieber').last
bieber_video.encode
# assume this takes a while...
bieber_video.encoding_in_process?
# => true
bieber_copy = Video.find_by_id bieber_video.id
bieber_copy.encoding_in_process?
# => false
# Each ActiveRecord objects refer to the same Bieber video
bieber_copy.id == bieber_video.id
# => true
# ...however they refer to different objects in memory:
puts bieber_video
#<Video:0x00000105a9e948>
puts bieber_copy
#<Video:0x00000105a11111>
# and hence each instance has a different version of commenting_locked?
# bieber_video.encoding_in_process? != bieber_copy.encoding_in_process?
问题
鉴于相同的数据库行可能会生成两个不同的内存中实例,那么存储有关这些实例的瞬时非数据库支持信息的安全方法是什么?
修改
我试图解决的实际问题是在启动destroy
时在对象上设置一个标志,以便其子对象可以确定它们是否有资格成为毁了自己。
因此,它是一个非常即时的问题,不适合备份到数据库中。我使用了这个视频的例子,因为我觉得它有点清晰但是我可能只是把水弄糊涂了。
解决方案(由以下答案之一提供
@Alex D的建议确实解决了这个问题,但是对于想要重复的人来说,为了进一步明确这个问题,实际的代码是这样的:
class Video
# set a class variable containing an array of all videos
# which are currently being encoded
@@ids_of_videos_being_encoded = []
...
def encode
store_encoding_state true
begin
encode()
ensure
# make sure we switch this off after
# encoding finishes or fails
store_encoding_state false
end
end
private
def store_encoding_state encoding_in_progress
if encoding_in_progress
@@ids_of_videos_being_encoded.push(id)
else
@@ids_of_videos_being_encoded.delete(id)
end
end
def encoding_initiated?
@@ids_of_videos_being_encoded.include? id
end
end
答案 0 :(得分:1)
因此,视频需要存储其当前的编码状态(是/否发生?)并允许子注释查询该属性。
IMO,这不是一个很好的方法,因为会出现所有同步问题。
更好的策略是启动unencoded
状态下的所有视频,并使用视频记录的元数据存储这些视频。创建视频数据流时,将某个工作人员的编码任务排入队列。工作线程将对视频进行编码,一旦完成,它应该将视频的状态更新为encoded
。
现在没有暂时的国家问题;下次有人在编码完成时尝试发表评论时,它就会完成。
鉴于相同的数据库行可能会生成两个不同的内存中实例,那么存储有关这些实例的瞬时非数据库支持信息的安全方法是什么?
如果不需要同步,那么就没有问题。如果他们做需要同步,则存在竞争条件的风险。您也可以调用.reload
从数据库中刷新对象的状态。
如果数据需要像这样同步,那么你可能做需要存储它。在视频编码示例中,您应该存储每个视频的编码/未编码状态,或者提供隐式的权威方式来了解视频是否已编码。
从原始问题更新:
我试图解决的实际问题是在启动销毁时在对象上设置一个标志,以便其子对象可以确定它们是否有资格自行销毁。
只需使用 after_destroy
callback 在每个子对象上调用适当的方法,让他们确定是否应该销毁它们。这看起来像这样:
class Video < ActiveRecord::Base
after_destroy :purge_pending_comments!
def purge_pending_comments!
comments.map &:destroy_if_pending
end
end
答案 1 :(得分:1)
您的问题的答案取决于您是否可以使用多个服务器进程。如果您可能想要运行多个服务器进程(这是一个很好的假设),问题不仅仅是代表相同数据库行的多个内存中ActiveRecord对象,问题是不同内存空间中的多个对象
如果您有多个进程以某种方式协同处理相同的数据,那么必须将该数据保存在共享存储(即数据库)中,并且您必须将更改刷新到商店,并且根据需要刷新内存中的数据。在这种情况下,不能依赖于瞬时内存数据保持同步(因为它可能无法实现)。
如果不断地向数据库写入/读取瞬态数据听起来很昂贵,那就是因为它。通常,只要您有多个进程(在相同或不同的服务器上)协同工作,您就需要设计一些东西,以便每个进程可以抓取一大块数据并在其上工作一段时间,而无需与其他进程通信。分布式系统中的细粒度数据共享=性能不佳。
如果您确定只使用单个服务器进程,并且想要模拟在表示相同数据库行的多个ActiveRecord对象之间共享的实例变量的效果,请将数据保存在哈希中,并键入记录ID,并使用读/写哈希的getters / setter。如果你正在做很多这样的事情,你可以做一些元编程“魔术”来自动生成getter / setter(la“attr_accessor”)。如果你需要帮助编写元编程代码,请发一个问题然后我会回答它。