Задать вопрос
@lookingfor2

Почему не видно лог?

Почему не видно лога u.logger.Debug("<- quit")?

И правильно ли я организовал работу между горутинами?
Может есть возможность упростить логику?

1. RunIssues перебирает модели и запускает в горутине workerStartPayment
2. workerStartPayment или отправляет в updateIssue или в workerCheckStatus

func (u *issueUC) workerCheckStatus(pi string, ch chan<- updateIssue, cfg *config.Config) {
	tiker := time.NewTicker(60 * time.Second)
	// канал отмены
	quit := make(chan struct{})
	count := 0
	for {
		select {
		case <-tiker.C:
			// если количество попыток равно 5, останавливаем выполнение опроса статуса
			if count == 10 {
				quit <- struct{}{}
			}
			count++
			// ------------------------
			status := payment.NewGetState(pi, cfg)
			status.Sign()
			statusResponse := status.Send()

			switch statusResponse.Status {

			case payment.StatusCompleted:
				u.logger.Debug("StatusCompleted stop work")
				ch <- updateIssue{
					Status:    models.IssueStatusSuccess,
					Success:   true,
					PaymentID: statusResponse.PaymentID,
					OrderID:   statusResponse.OrderID,
				}
				quit <- struct{}{}
			case payment.StatusRejected:
				u.logger.Debug("StatusRejected stop work")
				ch <- updateIssue{
					Status:    models.IssueStatusError,
					Success:   false,
					PaymentID: statusResponse.PaymentID,
					OrderID:   statusResponse.OrderID,
				}
				quit <- struct{}{}
			default:
				u.logger.Debug("default repeat work", statusResponse.OrderID, statusResponse.Status)
			}
		case <-quit:
			u.logger.Debug("<- quit")
		}
	}
}

func (u *issueUC) workerStartPayment(iss *models.Issue, ch chan<- updateIssue) {
	// инициализируем платежную сессию -------------------------
	init := payment.NewInit(
		iss.Guid,
		iss.PhoneNumber,
		iss.IdExternal,
		iss.Amount,
		iss.Details,
		u.cfg,
	)
	init.Sign()
	initResponse := init.Send()
	// инициализируем платежную сессию -------------------------

	// если не получилось инициализировать сессию бросаем результат в канал, чтобы обновить статус issue
	if initResponse.Status != payment.StatusChecked {
		ch <- updateIssue{
			Status:    models.IssueStatusError,
			Success:   false,
			PaymentID: initResponse.PaymentID,
			OrderID:   initResponse.OrderID,
		}
		return
	}

	// если сессия успешно инициализирована
	// выполняем пополнение счета по номеру телефона
	payment := payment.NewPaymentPayload(initResponse.PaymentID, u.cfg)
	payment.Sign()
	paymentResponse := payment.Send()
	// если не удалось выполнить пополнение бросаем результат в канал, чтобы обновить статус issue
	if paymentResponse.Status != payment.StatusCompleting {
		ch <- updateIssue{
			Status:    models.IssueStatusError,
			Success:   false,
			PaymentID: paymentResponse.PaymentID,
			OrderID:   paymentResponse.OrderID,
		}
		return
	}
	// начинаем опрашивать статус пополнения
	go u.workerCheckStatus(paymentResponse.PaymentID, ch, u.cfg)
}

func (u *issueUC) updateIssue(ch <-chan updateIssue) {
	for iss := range ch {
		err := u.repository.UpdateIssue(iss.OrderID, iss.Status, iss.Success)
		if err != nil {
			u.logger.Error("updateIssue UC, repo error")
			return
		}
	}
}

func (u *issueUC) RunIssues(issues []*models.Issue) error {

	updateIssueStatus := make(chan updateIssue, 1)

	for _, iss := range issues {
		go u.workerStartPayment(iss, updateIssueStatus)
	}
        // слушаю канал в горутине
	go u.updateIssue(updateIssueStatus)

	return nil
}
  • Вопрос задан
  • 154 просмотра
Подписаться 2 Простой 2 комментария
Пригласить эксперта
Ответы на вопрос 2
@AlekseiBadyaev
CTO, Skala Software
Так как канал quit не обладает буфером, то отправка сообщения в него блокируется. Если при инициализации задать размер буфера хотя бы 1, то в логе появится сообщение "<- quit".
Ответ написан
@falconandy
1. Канал quit не нужен - можно заменить на выход из цикла:
Loop:
	for {
		...
			if count == 10 {
				break Loop
			}
		...
	}

	log.Println("quit")


2. Тикер первый раз сработает не сразу, а только через 60 секунд (а main спит только 10 секунд). Надо разобраться с задержками, чтобы они соответствовали друг другу, или в main ждать не за счет sleep, а более явно (WaitGroup возможно).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы