mongodb / laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)
https://www.mongodb.com/docs/drivers/php/laravel-mongodb/
MIT License
7k stars 1.43k forks source link

Increment de registros ao mesmo tempo #2377

Open JefersonCelestino opened 2 years ago

JefersonCelestino commented 2 years ago

- Laravel: 9 - Laravel-mongodb Version: 3.9 - PHP Version: 8.1 - MongoDB extension version: 1.12.0 - Edition: MongoDB 5.0.6 Enterprise

Olá a todos, estou utilizando o seguinte método:

public function getNfeNumeroNext() { $this->nfe_numero_seq_atual = $this->nfe_numero_seq_atual + 1; $this->save(); return $this->nfe_numero_seq_atual; }

No qual o mesmo identifica o número atual e incrementa mais 1. Porém quando é realizado dois processos ao mesmo tempo, minuto e segundo. É salvo o mesmo número duas vezes, pois o mongo não esta conseguindo realizar dois updates ao mesmo tempo. Já tentei usar utilizar as seguintes soluções:

` / Teste utilizando lockForUpdate ou sharedLock / $company = self::lockForUpdate()->find($this->_id); $company = self::sharedLock()->find($this->_id); $company->nfe_numero_seq_atual = $company->nfe_numero_seq_atual + 1; $company->save(); return $company->nfe_numero_seq_atual;

/* Teste utilizando o increment */ 
$company = self::find($this->_id);
$company->increment('nfe_numero_seq_atual', 1);
$company->save();     
return $company->nfe_numero_seq_atual;

/* Teste utilizando o collection e increment */ 
$update_company = DB::collection('companies')->where('_id', $this->_id)->increment('nfe_numero_seq_atual', 1);
$company = DB::collection('companies')->find($this->_id);
return $company['nfe_numero_seq_atual'];` 

Alguma solução para o problema descrito? Obrigado por sua atenção, até mais.

andreefl commented 1 year ago

O Laravel fornece um método para trabalhar com Pessimistic Locking. Não posso afirmar se ele funciona bem com o MongoDB, mas vale a pena tentar. A lógica seria bloquear um registro enquanto está ocorrendo um update, dessa forma impedindo dois updates simultâneos.

Outra alternativa pode ser utilizar as filas do Laravel, criando um Job toda vez que for incrementar o número e ir processando os Jobs um por vez. Nesse caso o processamento ocorreria em background, não sei se atenderia o seu cenário.