Rails- 사용자가 동시에 동일한 데이터를 동시에 편집하는 것을 방지하기 위해 간단한 잠금을 구현합니다.
-
05-07-2019 - |
문제
다른 사용자가 편집하는 동안 사용자가 데이터를 편집하는 것을 방지 해야하는 앱이 있습니다. 나는 그것을하는 가장 좋은 방법을 생각하려고 노력하고 있으며 아이디어를 요청하고 싶었습니다. 지금까지 키/값 쌍의 DB에 응용 프로그램을 광범위하게 구성하는 설정 모델을 만들었습니다. 따라서 잠금의 경우 Locked_table_uid라고 불리는 설정 인스턴스가 있으며 테이블이 무료 인 경우 테이블 또는 NULL (NUL)을 편집하는 사용자의 user_id를 저장했습니다.
>> lock = Setting.find_by_key('LOCKED_TABLE_UID')
그런 다음 애플리케이션 컨트롤러에서 잠금을 획득하고 해제하기 위해 2 가지 방법을 구현했습니다.
# current_user returns the user currently logged in
def acquire_lock
lock = Setting.find_by_key("LOCKED_TABLE_UID")
if lock.value
# if lock taken, see if it's the current_user or someone else
if lock.value.to_i == current_user.id.to_i
return true
else
return false
end
else
# lock is free, assign it to this user
lock.value = current_user.id
return true if lock.save
end
end
def release_lock
lock = Setting.find_by_key("LOCKED_TABLE_UID")
if lock.value
# the lock belongs to current_user, so he can release it
if lock.value.to_i == current_user.id.to_i
lock.value = nil
return true if lock.save
else
# not your lock, go away
return false
end
else
# lock is free, quit bugging
return true
end
end
내가 원하는 것은 잠금 메커니즘을 포함하는 일종의 블록 코드를 만드는 것입니다.
def some_crud_action
requires_locking do |lock|
if lock
# do some CRUD stuff here
else
# decline CRUD and give some error
end
end
end
나는 이것에 대한 도움을 주셔서 감사합니다 - 그러나 나는 또한 모든 것을 성취하는 방법이나 내가 간과했을 수도있는 것들에 대한 다른 제안에도 열려 있습니다. 이 자물쇠는 원자 일 필요는 없지만 상당히 기본적이고 가장 중요합니다.
해결책
당신은 거의 거기에 있습니다. require_locking을 만드시겠습니까? 적합한 행동. 그런 다음 prever_filter로 처리하십시오.
before_filter :requires_locking?, :only => [:update, :destroy]
after_filter :release_lock, :only => [:update, :destroy]
def requires_locking do |lock|
unless acquire_lock
lock = Setting.find_by_key("LOCKED_TABLE_UID")
user_with_lock = User.find(lock.value)
flash[:message] = "Action denied: Table locked by: #{user_with_lock.name}"
redirect_to :back
end
end
다른 팁
나는 아이디어가 마음에 들지만 솔루션에 큰 문제가 있으며, 전체 테이블의 자물쇠를 얻고 공개하고 있다는 것입니다.
괜찮을 수있는 매우 작은 앱의 경우, 수천 명의 사용자가 '제품'테이블에 액세스하려고하고 누군가가 자신의 제품과 완전히 관련이없는 항목을 편집하고 있기 때문에 기다려야한다고 상상해보십시오.
어쩌면 당신은 더 미세한 곡물 접근 방식을 가질 수 있고 테이블 대신 특정 행을 잠글 수 있습니다. 잠금에는 테이블 이름, 행 ID 및 사용자 ID가 포함됩니다.
제 생각에는 acts_as_lockable_by GEM은 더 간단한 용어로 요청한 작업을 정확히하고 코드가 적습니다. 레일이나 베어 루비 프로젝트와 쉽게 통합 할 수 있습니다.
이 보석으로 원자력을 얻습니다 lock
, unlock
그리고 renew_lock
행동 양식. 또한 자동 만료를받습니다 ttl
잠금 장치, 똥이 팬에 부딪 치면 리소스를 잠금 해제 할 수 없으면 자동으로 잠금 해제됩니다!