eg

package module
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: BSD-3-Clause Imports: 18 Imported by: 0

README

easy-go

GoDev GitHub Telegram

Http request

RequestPost -

Пример использования:

res, err := eg.RequestPost(ctx, c.apiEndpoint+endpoint, bearerToken,
	req, nil, false,
)
if err != nil {
	if errors.Is(err, eg.ErrAuthFailed) {
		return nil, ErrNeedRefreshToken
	}

	log.Printf("SendOzonRequest: RequestPost: %s", err.Error())

	var data ozerror.OzonError
	errErr := json.Unmarshal(res, &data)
	if errErr != nil {
		log.Printf("Failed to Unmarshal error: %s", errErr.Error())
		return nil, fmt.Errorf("RequestPost: %w", err)
	}

	return nil, fmt.Errorf("RequestPost: %w [ERR_MESSAGE: %s]", err, data.Message)
}

Rate limited Queue

Queue - автоматическая очередь с обратной связью и рейт-лимитом (запросы не будут выполняться чаще заданного времени)

Пример использования:

func New(cfg *config.Config) *Connector {
	return &Connector{
		q:             eg.NewRateLimitedQueue(cfg.OzonConfig.CoolingTimeMillis),
		apiEndpoint:   cfg.OzonConfig.Endpoint,
		authEndpoint:  cfg.AuthConfig.Endpoint.AuthURL,
		tokenEndpoint: cfg.AuthConfig.Endpoint.TokenURL,
	}
}

// .....

func (c *Connector) DeliveryCheck(ctx context.Context, instance, clientPhone, bearerToken string) (bool, error) {
	log.Printf("sending delivery check request")
	out := make(chan *deliverycheck.Response)
	errOut := make(chan error)
	eg.PushToQueue(
		c.q,
		instance,
		func() (any, error) {
			res, err := eg.RequestPost(ctx, c.apiEndpoint+deliverycheck.Endpoint, bearerToken,
				&deliverycheck.Request{
					ClientPhone: clientPhone,
				}, nil,
				true,
			)
			if err != nil {
				if errors.Is(err, eg.ErrAuthFailed) {
					return nil, ErrNeedRefreshToken
				}

				var data ozerror.OzonError
				errErr := json.Unmarshal(res, &data)
				if errErr != nil {
					log.Printf("Failed to Unmarshal error: %s", errErr.Error())
				}

				return nil, fmt.Errorf("RequestPost: %w [ERR_MESSAGE: %s]", err, data.Message)
			}

			var data deliverycheck.Response
			err = json.Unmarshal(res, &data)
			if err != nil {
				return nil, fmt.Errorf("Unmarshal: %w", err)
			}

			return &data, nil
		},
		out,
		errOut,
	)

	log.Printf("send delivery check request")

	r := <-out

	err := <-errOut
	if err != nil {
		return false, fmt.Errorf("err: %w", err)
	}

	log.Printf("got delivery check response: %v", r)

	if r == nil {
		return false, fmt.Errorf("got nil response")
	}

	return r.IsPossible, nil
}

Server + S2S

Server - пример использования:

func Run(cfg *config.Config) {
	handlers := &Handlers{
		s: service.New(cfg),
	}

	eg.NewServer().
		HandleRawAll(eg.RawHandleMap{
			"/api/v1/app/callback": handlers.a.HandleCallback,
			"/api/v1/app/login":    handlers.a.HandleLogin,
			"/api/v1/app/link":     handlers.a.HandleLink,
		}).
		HandleAll(eg.HandleMap{
			"/health":                   handlers.Health,
			"/api/v1/token/generate":    handlers.GenerateToken,
			"/api/v1/token/save":        handlers.SaveToken,
		}).
		HandleAllWithS2S(eg.HandleMap{
			models.MethodReceive:        handlers.ReceiveNotification,
			"/api/v1/notification/init": handlers.InitializeSellersSubscriptions,
		}).
		HandleAll(handlers.handleOzonMethods()).
		Start()
}

func (serv *Handlers) handleOzonMethods() eg.HandleMap {
	hm := make(eg.HandleMap, len(models.OzonMethodMap))
	for method, ozonMethod := range models.OzonMethodMap {
		hm[method] = serv.Ozon(ozonMethod)
	}
	return hm
}

Kafka

Producer - пример использования:


producer := eg.NewKafkaProducer(
	os.Getenv("KAFKA_BROKERS"), 
	os.Getenv("KAFKA_USER"), 
	os.Getenv("KAFKA_PASSWORD"),
)

// ...

testValue := TestStruct{
	MVDrive: "platform",
	By:      "Nikolai Kozakov"
}

err := producer.Produce(os.Getenv("KAFKA_TEST_TOPIC"), uuid.NewString(), testValue)
if err != nil {
	return fmt.Errorf("Produce: %w", err)
}

Consumer - пример использования:


consumer := eg.NewKafkaConsumer(
	os.Getenv("KAFKA_BROKERS"), 
	os.Getenv("KAFKA_GROUP_ID"),
	os.Getenv("KAFKA_USER"), 
	os.Getenv("KAFKA_PASSWORD"),
)

// ...

testSource, err := consumer.Consume(ctx, os.Getenv("KAFKA_TEST_TOPIC"))
if err != nil {
	return fmt.Errorf("Consume: %w", err)
}

go func(){
	for message := range testSource {
		log.Printf("got message: key = %v, value = %v", message.Key, message.Value)
	}
}()

Documentation

Index

Constants

View Source
const (
	S2SEnvKey    = "EG_S2S_AUTH_KEY"
	S2SHeaderKey = "X-EG-S2S-Authorization"
)
View Source
const (
	EGFunctionTypeUnknown = iota
	EGFunctionTypeDefault
	EGFunctionTypeValue
	EGFunctionTypeResult
)

Variables

View Source
var ErrAuthFailed = errors.New("auth failed")

Functions

func ChanSelect

func ChanSelect(selector Selector) bool

ChanSelect - like go select (NOTE: blocking call, size of selector must be min 1 and max 3 Chan + min 0 and max 1 SelectorDefault, otherwise panic) - returns true once the Returner is selected

func FuncEqual

func FuncEqual(func1, func2 any) bool

func GetFunctionType

func GetFunctionType[T any](f any) int

func Handler

func Handler(f StandardHandler, useS2S bool) func(w http.ResponseWriter, r *http.Request)

func PushToQueue

func PushToQueue[R any](q *Queue, instance string, operation func() (any, error), out *Chan[R], errOut *Chan[error])

func RequestPost

func RequestPost(
	ctx context.Context,
	endpoint, bearerToken string,
	body any, headers map[string]string,
	bodyIsRawBytes bool,
) ([]byte, error)

func Returner

func Returner(any)

func WaitConcurrentExec

func WaitConcurrentExec[F egFunction[T], T any](threads ...*Thread[F, T])

Types

type Chan

type Chan[T any] struct {
	// contains filtered or unexported fields
}

Chan - user-friendly chan without "<-" and "->"

var SelectorDefault *Chan[selectorDefault]

func NewChan

func NewChan[T any]() *Chan[T]

NewChan - create a new Chan with data transfer type T

func (*Chan[T]) AbstractOriginal

func (c *Chan[T]) AbstractOriginal() reflect.Value

AbstractOriginal - just don't use it, trust me

func (*Chan[T]) Close

func (c *Chan[T]) Close()

Close - closes the Chan (below this point Write will be unavailable)

func (*Chan[T]) GetType

func (c *Chan[T]) GetType() reflect.Type

GetType - returns reflect Type of T

func (*Chan[T]) Original

func (c *Chan[T]) Original() chan T

Original - get a go chan (not sure you really want it)

func (*Chan[T]) Read

func (c *Chan[T]) Read() T

Read - read a value from the Chan (blocking call until any eg.Thread or goroutine writes anything in it)

func (*Chan[T]) Write

func (c *Chan[T]) Write(v T)

Write - panic-free putting a value in the Chan (blocking call until any eg.Thread or goroutine reads from it, does nothing if the Chan is closed)

type HandleMap

type HandleMap map[string]StandardHandler

type IChan

type IChan interface {
	GetType() reflect.Type
	AbstractOriginal() reflect.Value
}

type KafkaConsumer

type KafkaConsumer struct {
	// contains filtered or unexported fields
}

func NewKafkaConsumer

func NewKafkaConsumer(brokers, groupID, topic, username, password string) *KafkaConsumer

func (*KafkaConsumer) Consume

func (kp *KafkaConsumer) Consume(ctx context.Context) (*Chan[*KafkaMessage], error)

type KafkaMessage

type KafkaMessage struct {
	Key   string
	Value any
}

type KafkaProducer

type KafkaProducer struct {
	// contains filtered or unexported fields
}

func NewKafkaProducer

func NewKafkaProducer(brokers, username, password string) *KafkaProducer

func (*KafkaProducer) Close

func (kp *KafkaProducer) Close()

func (*KafkaProducer) Produce

func (kp *KafkaProducer) Produce(ctx context.Context, topic, key string, value any) error

type Queue

type Queue struct {
	// contains filtered or unexported fields
}

func NewRateLimitedQueue

func NewRateLimitedQueue(timeoutMillis int64) *Queue

func (*Queue) TerminateQueue

func (q *Queue) TerminateQueue(instance string)

type QueueObject

type QueueObject struct {
	// contains filtered or unexported fields
}

type RawHandleMap

type RawHandleMap map[string]RawHandler

type RawHandler

type RawHandler func(w http.ResponseWriter, r *http.Request)

type Selector

type Selector map[IChan]func(any)

func (Selector) GetStructure

func (s Selector) GetStructure() ([]IChan, IChan)

type Server

type Server struct {
	// contains filtered or unexported fields
}

func NewServer

func NewServer() *Server

func (*Server) Handle

func (s *Server) Handle(apiEoute string, handler StandardHandler, useS2S bool) *Server

func (*Server) HandleAll

func (s *Server) HandleAll(handleMap HandleMap) *Server

func (*Server) HandleAllWithS2S

func (s *Server) HandleAllWithS2S(handleMap HandleMap) *Server

func (*Server) HandleRaw

func (s *Server) HandleRaw(apiEoute string, handler RawHandler) *Server

func (*Server) HandleRawAll

func (s *Server) HandleRawAll(handleMap RawHandleMap) *Server

func (*Server) Start

func (s *Server) Start()

type Slice

type Slice[T any] struct {
	// contains filtered or unexported fields
}

Slice - user-friendly and concurrent-friendly slice []T without go-style crap like a = append(a, b)

func NewSlice

func NewSlice[T any](elems ...T) *Slice[T]

NewSlice - create new Slice of type T - elems may be empty (NOTE: returns a pointer)

func NewSliceOfSize

func NewSliceOfSize[T any](size int64) *Slice[T]

NewSlice - create new Slice of type with given go-slice capacity (NOTE: returns a pointer)

func WorkThreads

func WorkThreads[F egFunction[T], T any](threads ...*Thread[F, T]) *Slice[T]

func (*Slice[T]) Append

func (s *Slice[T]) Append(elems ...T) *Slice[T]

Append - Python-styled "b = append(b, a)" operation - appends elems to the end of the inner go slice

func (*Slice[T]) Copy

func (s *Slice[T]) Copy() *Slice[T]

Copy - safe copy of the Slice object (NOTE: lock is not copied, so the return Slice is completely independent)

func (*Slice[T]) Cut

func (s *Slice[T]) Cut(start, end int64) *Slice[T]

Cut - panic-free slicing of the Slice - returns new Slice with the inner slice as example[start:end] (NOTE: start < end, start >= 0 and end < Size - otherwise it edits start and end to fit in bounds)

func (*Slice[T]) Enlarge

func (s *Slice[T]) Enlarge(newSize int64)

Enlarge - adds some default values of T to the end, does nothing if newSize <= Size()

func (*Slice[T]) Erase

func (s *Slice[T]) Erase()

Erase - drops all the values (size will be 0) but keeps capacity the same as size was

func (*Slice[T]) Extend

func (s *Slice[T]) Extend(another *Slice[T]) *Slice[T]

Extend - the same as Append but joins two objects of eg.Slice - returns the first of them and keeps another unchanged

func (*Slice[T]) Get

func (s *Slice[T]) Get(idx int64) T

Get - panic-free "a = b[idx]" operation - returns value if idx is in bounds and default of type T otherwise

func (*Slice[T]) IsEmpty

func (s *Slice[T]) IsEmpty() bool

IsEmpty - true if there are no values in it (capacity may not be 0)

func (*Slice[T]) Original

func (s *Slice[T]) Original() []T

Original - returns go slice from the inside (just in case you need it)

func (*Slice[T]) Prepend

func (s *Slice[T]) Prepend(elems ...T) *Slice[T]

Prepend - Python-styled "b = append(a, b)" operation - appends elems before the inner go slice

func (*Slice[T]) ResetToDefault

func (s *Slice[T]) ResetToDefault()

ResetToDefault - replaces all the values with default of type T (NOTE: not recommended, better use Erase())

func (*Slice[T]) Set

func (s *Slice[T]) Set(idx int64, value T)

Set - panic-free "b[idx] = a" operation - sets value if idx >= 0 and does nothing otherwise (NOTE: if idx >= Size(), it enlarges the Slice - see Enlarge())

func (*Slice[T]) Size

func (s *Slice[T]) Size() int64

Size - size of go slice from the inside (not capacity)

func (*Slice[T]) Vanish

func (s *Slice[T]) Vanish()

Vanish - completely vanishes the Slice - 0 len and 0 cap left

type StandardHandler

type StandardHandler func(ctx context.Context, body io.Reader, method string) (any, error)

type Thread

type Thread[F egFunction[T], T any] struct {
	// contains filtered or unexported fields
}

func NewThread

func NewThread[F egFunction[T], T any](routine F) *Thread[F, T]

NewThread creates new Thread for one of the egFunction[T]

func (*Thread[F, T]) After

func (t *Thread[F, T]) After(previous *Thread[F, T]) *Thread[F, T]

func (*Thread[F, T]) Function

func (t *Thread[F, T]) Function() F

func (*Thread[F, T]) MaybeStart

func (t *Thread[F, T]) MaybeStart(goInited bool) threadResult[T]

func (*Thread[F, T]) Position

func (t *Thread[F, T]) Position() int

func (*Thread[F, T]) Run

func (t *Thread[F, T]) Run()

func (*Thread[F, T]) SetExecuted

func (t *Thread[F, T]) SetExecuted()

func (*Thread[F, T]) Started

func (t *Thread[F, T]) Started() bool

func (*Thread[F, T]) String

func (t *Thread[F, T]) String() string

func (*Thread[F, T]) Then

func (t *Thread[F, T]) Then(next *Thread[F, T]) *Thread[F, T]

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL