mirror of
https://github.com/ManyakRus/starter.git
synced 2025-11-23 22:45:11 +02:00
278 lines
7.7 KiB
Go
278 lines
7.7 KiB
Go
// модуль для обмена с сервисом NATS через sync_exchange
|
|
package sync_exchange_connect
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"github.com/ManyakRus/starter/contextmain"
|
|
"github.com/ManyakRus/starter/log"
|
|
"github.com/ManyakRus/starter/nats_connect"
|
|
"github.com/ManyakRus/starter/stopapp"
|
|
"gitlab.aescorp.ru/dsp_dev/claim/common/sync_exchange"
|
|
"gitlab.aescorp.ru/dsp_dev/claim/common/sync_exchange/sync_types"
|
|
"os"
|
|
"runtime/pprof"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// TopicNamePprof_Heap_Suffix - имя суффикса топика с профилем памяти
|
|
const TopicNamePprof_Heap_Suffix = ".heap_profile"
|
|
|
|
// TopicNamePprof_Goroutine_Suffix - имя суффикса топика с профилем памяти
|
|
const TopicNamePprof_Goroutine_Suffix = ".goroutine_profile"
|
|
|
|
// serviceName - имя сервиса который подключается
|
|
var serviceName string
|
|
|
|
// Connect - подключение к NATS SyncExchange
|
|
func Connect(ServiceName, ServiceVersion string) {
|
|
err := Connect_err(ServiceName, ServiceVersion)
|
|
LogInfo_Connected(err)
|
|
}
|
|
|
|
// LogInfo_Connected - выводит сообщение в Лог, или паника при ошибке
|
|
func LogInfo_Connected(err error) {
|
|
if err != nil {
|
|
log.Panicln("Can not start NATS, server: ", nats_connect.Settings.NATS_HOST, " error: ", err)
|
|
} else {
|
|
log.Info("NATS connected. OK., server: ", nats_connect.Settings.NATS_HOST, ":", nats_connect.Settings.NATS_PORT)
|
|
}
|
|
|
|
}
|
|
|
|
// Connect_err - подключение к NATS SyncExchange
|
|
func Connect_err(ServiceName, ServiceVersion string) error {
|
|
var err error
|
|
|
|
//запомним ServiceName
|
|
if serviceName == "" {
|
|
serviceName = ServiceName
|
|
}
|
|
|
|
//
|
|
nats_connect.FillSettings()
|
|
sNATS_PORT := (nats_connect.Settings.NATS_PORT)
|
|
url := "nats://" + nats_connect.Settings.NATS_HOST + ":" + sNATS_PORT
|
|
|
|
err = sync_exchange.InitSyncExchange(url, ServiceName, ServiceVersion)
|
|
|
|
return err
|
|
}
|
|
|
|
// Start - необходимые процедуры для подключения к серверу Nats SyncExchange
|
|
func Start(ServiceName, ServiceVersion string) {
|
|
var err error
|
|
|
|
ctx := contextmain.GetContext()
|
|
WaitGroup := stopapp.GetWaitGroup_Main()
|
|
err = Start_ctx(&ctx, WaitGroup, ServiceName, ServiceVersion)
|
|
LogInfo_Connected(err)
|
|
|
|
}
|
|
|
|
// Start_ctx - необходимые процедуры для подключения к NATS с библиотекой SyncExchange
|
|
// Свой контекст и WaitGroup нужны для остановки работы сервиса Graceful shutdown
|
|
// Для тех кто пользуется этим репозиторием для старта и останова сервиса можно просто Start()
|
|
func Start_ctx(ctx *context.Context, WaitGroup *sync.WaitGroup, ServiceName, ServiceVersion string) error {
|
|
var err error
|
|
|
|
//запомним к себе контекст
|
|
if contextmain.Ctx != ctx {
|
|
contextmain.SetContext(ctx)
|
|
}
|
|
//contextmain.Ctx = ctx
|
|
if ctx == nil {
|
|
contextmain.GetContext()
|
|
}
|
|
|
|
//запомним к себе WaitGroup
|
|
stopapp.SetWaitGroup_Main(WaitGroup)
|
|
if WaitGroup == nil {
|
|
stopapp.StartWaitStop()
|
|
}
|
|
|
|
//
|
|
err = Connect_err(ServiceName, ServiceVersion)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
stopapp.GetWaitGroup_Main().Add(1)
|
|
go WaitStop()
|
|
|
|
return err
|
|
}
|
|
|
|
// CloseConnection - закрывает соединение с NATS
|
|
func CloseConnection() {
|
|
err := sync_exchange.DeInitSyncExchange()
|
|
if err != nil {
|
|
log.Error("CloseConnection() error: ", err)
|
|
} else {
|
|
log.Info("NATS stopped")
|
|
}
|
|
|
|
//return err
|
|
}
|
|
|
|
// WaitStop - ожидает отмену глобального контекста или сигнала завершения приложения
|
|
func WaitStop() {
|
|
defer stopapp.GetWaitGroup_Main().Done()
|
|
|
|
select {
|
|
case <-contextmain.GetContext().Done():
|
|
log.Warn("Context app is canceled. sync_exchange_connect")
|
|
}
|
|
|
|
//ждём пока отправляемых сейчас сообщений будет =0
|
|
stopapp.WaitTotalMessagesSendingNow("sync_exchange_connect")
|
|
|
|
//закрываем соединение
|
|
CloseConnection()
|
|
}
|
|
|
|
// SendResponseError - Отправляет ответ в NATS SyncExchange
|
|
func SendResponseError(sp *sync_types.SyncPackage, err error) {
|
|
|
|
if err == nil {
|
|
return
|
|
}
|
|
|
|
sp_otvet := sync_types.MakeSyncError("", 0, err.Error())
|
|
|
|
err = sync_exchange.SendResponse(sp, sp_otvet)
|
|
if err != nil {
|
|
log.Error("SendResponse() Error: ", err)
|
|
}
|
|
|
|
}
|
|
|
|
// Start_PprofNats - профилирование памяти отправляет в NATS, бесконечно + WaitGroup
|
|
func Start_PprofNats() {
|
|
TextTest := TextTestOrEmpty()
|
|
topicHeapProfile := serviceName + TextTest + TopicNamePprof_Heap_Suffix
|
|
log.Info("Start_PprofNats(), topic: ", topicHeapProfile)
|
|
|
|
stopapp.GetWaitGroup_Main().Add(1)
|
|
go pprofNats_forever_go()
|
|
}
|
|
|
|
// pprofNats_forever_go - профилирование памяти отправляет в NATS, бесконечно + WaitGroup
|
|
func pprofNats_forever_go() {
|
|
defer stopapp.GetWaitGroup_Main().Done()
|
|
PprofNats_forever()
|
|
}
|
|
|
|
// PprofNats_forever - профилирование памяти отправляет в NATS, бесконечно
|
|
func PprofNats_forever() {
|
|
var err error
|
|
|
|
ticker := time.NewTicker(60 * time.Second)
|
|
defer ticker.Stop()
|
|
|
|
loop:
|
|
for {
|
|
select {
|
|
case <-contextmain.GetContext().Done():
|
|
log.Warn("Context app is canceled. sync_exchange_connect.ping")
|
|
break loop
|
|
case <-ticker.C:
|
|
err = PprofNats1()
|
|
if err != nil {
|
|
err = fmt.Errorf("PprofNats1(), error: %w", err)
|
|
log.Error(err)
|
|
time.Sleep(60 * time.Second)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// PprofNats1 - профилирование памяти отправляет в NATS 1 раз
|
|
func PprofNats1() error {
|
|
var err error
|
|
|
|
//память
|
|
err = PprofMemoryProfile1()
|
|
if err != nil {
|
|
err = fmt.Errorf("PprofMemoryProfile1(), error: %w", err)
|
|
log.Error(err)
|
|
return err
|
|
}
|
|
|
|
//горутины
|
|
err = PprofGoroutines1()
|
|
if err != nil {
|
|
err = fmt.Errorf("PprofMemoryProfile1(), error: %w", err)
|
|
log.Error(err)
|
|
return err
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// PprofMemoryProfile1 - профилирование памяти отправляет в NATS 1 раз
|
|
func PprofMemoryProfile1() error {
|
|
var err error
|
|
|
|
TextTest := TextTestOrEmpty()
|
|
topicHeapProfile := serviceName + TextTest + TopicNamePprof_Heap_Suffix
|
|
var buf bytes.Buffer
|
|
err = pprof.WriteHeapProfile(&buf)
|
|
if err != nil {
|
|
err = fmt.Errorf("pprof.WriteHeapProfile(), topic: %v, error: %w", topicHeapProfile, err)
|
|
log.Error(err)
|
|
time.Sleep(10 * time.Second)
|
|
return err
|
|
}
|
|
err = sync_exchange.SendRawMessage(topicHeapProfile, buf.Bytes())
|
|
if err != nil {
|
|
err = fmt.Errorf("sync_exchange.SendRawMessage(), topic: %v, error: %w", topicHeapProfile, err)
|
|
log.Error(err)
|
|
time.Sleep(10 * time.Second)
|
|
return err
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// PprofGoroutines1 - профилирование горутин отправляет в NATS 1 раз
|
|
func PprofGoroutines1() error {
|
|
var err error
|
|
|
|
TextTest := TextTestOrEmpty()
|
|
topicHeapProfile := serviceName + TextTest + TopicNamePprof_Goroutine_Suffix
|
|
var buf bytes.Buffer
|
|
err = pprof.Lookup("goroutine").WriteTo(&buf, 2)
|
|
if err != nil {
|
|
err = fmt.Errorf("pprof.WriteHeapProfile(), topic: %v, error: %w", topicHeapProfile, err)
|
|
log.Error(err)
|
|
time.Sleep(10 * time.Second)
|
|
return err
|
|
}
|
|
err = sync_exchange.SendRawMessage(topicHeapProfile, buf.Bytes())
|
|
if err != nil {
|
|
err = fmt.Errorf("sync_exchange.SendRawMessage(), topic: %v, error: %w", topicHeapProfile, err)
|
|
log.Error(err)
|
|
time.Sleep(10 * time.Second)
|
|
return err
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// TextTestOrEmpty - возвращает "_test" или ""
|
|
func TextTestOrEmpty() string {
|
|
Otvet := "_test"
|
|
stage := os.Getenv("STAGE")
|
|
switch stage {
|
|
case "dev":
|
|
Otvet = ""
|
|
case "prod":
|
|
Otvet = ""
|
|
}
|
|
|
|
return Otvet
|
|
}
|