Skip to content

Commit

Permalink
fix: database locked error
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielolivrp committed Nov 5, 2023
1 parent 0a3f78b commit d403bfe
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 25 deletions.
20 changes: 18 additions & 2 deletions configs/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type ZapMeow struct {
WhatsmeowContainer *sqlstore.Container
DatabaseClient *gorm.DB
RedisClient *redis.Client
Instances map[string]*Instance
Instances *sync.Map
Config ZapMeowConfig
Wg *sync.WaitGroup
Mutex *sync.Mutex
Expand All @@ -29,7 +29,7 @@ func NewZapMeow(
whatsmeowContainer *sqlstore.Container,
databaseClient *gorm.DB,
redisClient *redis.Client,
instances map[string]*Instance,
instances *sync.Map,
config ZapMeowConfig,
wg *sync.WaitGroup,
mutex *sync.Mutex,
Expand All @@ -46,3 +46,19 @@ func NewZapMeow(
StopCh: stopCh,
}
}

func (a *ZapMeow) LoadInstance(instanceID string) *Instance {
value, _ := a.Instances.Load(instanceID)
if value != nil {
return value.(*Instance)
}
return nil
}

func (a *ZapMeow) StoreInstance(instanceID string, instance *Instance) {
a.Instances.Store(instanceID, instance)
}

func (a *ZapMeow) DeleteInstance(instanceID string) {
a.Instances.Delete(instanceID)
}
6 changes: 6 additions & 0 deletions controllers/get_qrcode_controller.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package controllers

import (
"zapmeow/configs"
"zapmeow/services"
"zapmeow/utils"

"github.com/gin-gonic/gin"
)

type getQrCodeController struct {
app *configs.ZapMeow
wppService services.WppService
messageService services.MessageService
accountService services.AccountService
Expand All @@ -18,11 +20,13 @@ type getQrCodeResponse struct {
}

func NewGetQrCodeController(
app *configs.ZapMeow,
wppService services.WppService,
messageService services.MessageService,
accountService services.AccountService,
) *getQrCodeController {
return &getQrCodeController{
app: app,
wppService: wppService,
messageService: messageService,
accountService: accountService,
Expand All @@ -46,6 +50,8 @@ func (q *getQrCodeController) Handler(c *gin.Context) {
return
}

q.app.Mutex.Lock()
defer q.app.Mutex.Unlock()
account, err := q.accountService.GetAccountByInstanceID(instanceID)
if err != nil {
utils.RespondInternalServerError(c, err.Error())
Expand Down
6 changes: 6 additions & 0 deletions controllers/get_status_controller.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package controllers

import (
"zapmeow/configs"
"zapmeow/services"
"zapmeow/utils"

"github.com/gin-gonic/gin"
)

type getStatusController struct {
app *configs.ZapMeow
wppService services.WppService
accountService services.AccountService
}
Expand All @@ -17,10 +19,12 @@ type getStatusResponse struct {
}

func NewGetStatusController(
app *configs.ZapMeow,
wppService services.WppService,
accountService services.AccountService,
) *getStatusController {
return &getStatusController{
app: app,
wppService: wppService,
accountService: accountService,
}
Expand All @@ -44,6 +48,8 @@ func (s *getStatusController) Handler(c *gin.Context) {
return
}

s.app.Mutex.Lock()
defer s.app.Mutex.Unlock()
account, err := s.accountService.GetAccountByInstanceID(instanceID)
if err != nil {
utils.RespondInternalServerError(c, err.Error())
Expand Down
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func main() {
}

// whatsmeow instances
instances := make(map[string]*configs.Instance)
var instances sync.Map

// whatsmeow configs
dbLog := waLog.Stdout("Database", "DEBUG", true)
Expand Down Expand Up @@ -88,7 +88,7 @@ func main() {
whatsmeowContainer,
databaseClient,
redisClient,
instances,
&instances,
config,
&wg,
&mutex,
Expand Down
2 changes: 2 additions & 0 deletions routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func SetupRouter(
}

getQrCodeController := controllers.NewGetQrCodeController(
app,
wppService,
messageService,
accountService,
Expand All @@ -38,6 +39,7 @@ func SetupRouter(
accountService,
)
getStatusController := controllers.NewGetStatusController(
app,
wppService,
accountService,
)
Expand Down
43 changes: 23 additions & 20 deletions services/wpp_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ func NewWppService(
}

func (w *wppService) GetInstance(instanceID string) (*configs.Instance, error) {
instance, ok := w.app.Instances[instanceID]
instance := w.app.LoadInstance(instanceID)

if ok && instance != nil {
if instance != nil {
return instance, nil
}

Expand All @@ -125,28 +125,31 @@ func (w *wppService) GetInstance(instanceID string) (*configs.Instance, error) {
return nil, err
}

w.app.Instances[instanceID] = &configs.Instance{
w.app.StoreInstance(instanceID, &configs.Instance{
ID: instanceID,
Client: client,
}
w.app.Instances[instanceID].Client.AddEventHandler(func(evt interface{}) {
})

instance = w.app.LoadInstance(instanceID)

instance.Client.AddEventHandler(func(evt interface{}) {
w.eventHandler(instanceID, evt)
})

if w.app.Instances[instanceID].Client.Store.ID == nil {
if instance.Client.Store.ID == nil {
go w.qrcode(instanceID)
} else {
err := w.app.Instances[instanceID].Client.Connect()
err := instance.Client.Connect()
if err != nil {
return nil, err
}

if !w.app.Instances[instanceID].Client.WaitForConnection(5 * time.Second) {
if !instance.Client.WaitForConnection(5 * time.Second) {
return nil, errors.New("websocket didn't reconnect within 5 seconds of failed")
}
}

return w.app.Instances[instanceID], nil
return instance, nil
}

func (w *wppService) GetAuthenticatedInstance(instanceID string) (*configs.Instance, error) {
Expand Down Expand Up @@ -392,7 +395,7 @@ func (w *wppService) destroyInstance(instanceID string) error {
}

instance.Client.Disconnect()
delete(w.app.Instances, instanceID)
w.app.DeleteInstance(instanceID)

return nil
}
Expand Down Expand Up @@ -503,7 +506,7 @@ func (w *wppService) getClient(instanceID string) (*whatsmeow.Client, error) {
}

func (w *wppService) qrcode(instanceID string) {
instance := w.app.Instances[instanceID]
instance := w.app.LoadInstance(instanceID)
if instance.Client.Store.ID == nil {
qrChan, err := instance.Client.GetQRChannel(context.Background())
if err != nil {
Expand All @@ -521,28 +524,28 @@ func (w *wppService) qrcode(instanceID string) {
case "success":
return
case "timeout":
for {
w.app.Mutex.Lock()
{
// w.app.Mutex.Lock()
// defer w.app.Mutex.Unlock()
err := w.accountService.UpdateAccount(instanceID, map[string]interface{}{
"QrCode": "",
"Status": "TIMEOUT",
})
w.app.Mutex.Unlock()
if err != nil {
fmt.Println("[qrcode]: ", err)
}

delete(w.app.Instances, instanceID)
w.app.DeleteInstance(instanceID)
}
case "code":
for {
w.app.Mutex.Lock()
{
// w.app.Mutex.Lock()
// defer w.app.Mutex.Unlock()
w.accountService.UpdateAccount(instanceID, map[string]interface{}{
"QrCode": evt.Code,
"Status": "UNPAIRED",
"WasSynced": false,
})
w.app.Mutex.Unlock()
if err != nil {
fmt.Println("[qrcode]: ", err)
}
Expand Down Expand Up @@ -581,7 +584,7 @@ func (w *wppService) handleHistorySync(instanceID string, evt *events.HistorySyn
}

func (w *wppService) handleConnected(instanceID string) {
var instance = w.app.Instances[instanceID]
var instance = w.app.LoadInstance(instanceID)
err := w.accountService.UpdateAccount(instanceID, map[string]interface{}{
"User": instance.Client.Store.ID.User,
"Agent": instance.Client.Store.ID.Agent,
Expand Down Expand Up @@ -615,7 +618,7 @@ func (w *wppService) handleLoggedOut(instanceID string) {
}

func (w *wppService) handleMessage(instanceId string, evt *events.Message) {
instance := w.app.Instances[instanceId]
instance := w.app.LoadInstance(instanceId)
parsedEventMessage, err := w.ParseEventMessage(instance, evt)

if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion workers/history_sync_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (q *historySyncWorker) ProcessQueue() {
continue
}

instance := q.app.Instances[data.InstanceID]
instance := q.app.LoadInstance(data.InstanceID)
account, err := q.accountService.GetAccountByInstanceID(data.InstanceID)
if err != nil {
fmt.Println(err)
Expand Down

0 comments on commit d403bfe

Please sign in to comment.