Problema de concorrência em campos personalizados

Às vezes, encontramos problemas de concorrência com campos personalizados.

Um exemplo é um manipulador de webhook que faz isso

user_id = params[:externalUserId].split('-')[1]
user = User.find_by(id: user_id)
raise Discourse::NotFound unless user

... faz muito processamento ...

user.custom_fields[:myfield] = params[:whatever]
user.save_custom_fields

Quando dois webhooks são acionados em rápida sucessão para o mesmo usuário, às vezes acabamos com uma linha duplicada. Da próxima vez que os campos personalizados do usuário forem acessados, eles parecerão
{"myfield"=>["value", "value"]}

Vejo que (user_id, name) é definido como um índice, mas não exclusivo em user_custom_fields.

Qual seria o melhor padrão para evitar que isso aconteça?

4 curtidas