Sam 2013-11-26 10:21:41 +11:00
parent 2eee7433f0
commit 3fa48f8d76
3 changed files with 28 additions and 22 deletions

View File

@ -29,8 +29,9 @@ class PostsController < ApplicationController
params = create_params
key = params_key(params)
error_json = nil
result = DistributedMemoizer.memoize(key, 120) do
payload = DistributedMemoizer.memoize(key, 120) do
post_creator = PostCreator.new(current_user, params)
post = post_creator.create
if post_creator.errors.present?
@ -38,24 +39,21 @@ class PostsController < ApplicationController
# If the post was spam, flag all the user's posts as spam
current_user.flag_linked_posts_as_spam if post_creator.spam?
"e" << MultiJson.dump(errors: post_creator.errors.full_messages)
error_json = MultiJson.dump(errors: post_creator.errors.full_messages)
raise Discourse::InvalidPost
else
post_serializer = PostSerializer.new(post, scope: guardian, root: false)
post_serializer.topic_slug = post.topic.slug if post.topic.present?
post_serializer.draft_sequence = DraftSequence.current(current_user, post.topic.draft_key)
"s" << MultiJson.dump(post_serializer)
MultiJson.dump(post_serializer)
end
end
render json: payload
payload = result[1..-1]
if result[0] == "e"
# don't memoize errors
$redis.del(DistributedMemoizer.redis_key(key))
render json: payload, status: 422
else
render json: payload
end
rescue Discourse::InvalidPost
render json: error_json, status: 422
end
def update
@ -157,7 +155,6 @@ class PostsController < ApplicationController
posts.each {|p| guardian.ensure_can_delete!(p) }
Post.transaction do
topic_id = posts.first.topic_id
posts.each {|p| PostDestroyer.new(current_user, p).destroy }
end

View File

@ -25,6 +25,8 @@ module Discourse
# When ImageMagick is missing
class ImageMagickMissing < Exception; end
class InvalidPost < Exception; end
# Cross site request forgery
class CSRF < Exception; end

View File

@ -15,18 +15,25 @@ class DistributedMemoizer
start = Time.new
got_lock = false
while Time.new < start + MAX_WAIT && !got_lock
LOCK.synchronize do
got_lock = get_lock(redis,redis_lock_key)
end
sleep 0.001
end
unless result = redis.get(redis_key)
result = yield
redis.setex(redis_key, duration, result)
begin
while Time.new < start + MAX_WAIT && !got_lock
LOCK.synchronize do
got_lock = get_lock(redis,redis_lock_key)
end
sleep 0.001
end
unless result = redis.get(redis_key)
result = yield
redis.setex(redis_key, duration, result)
end
ensure
# NOTE: delete regardless so next one in does not need to wait MAX_WAIT
# again
redis.del(redis_lock_key)
end
redis.del(redis_lock_key)
end
result