Browse Source

[fix] conflict

pull/1/head
loveckiy.ivan 2 months ago
parent
commit
264f30a4c9
  1. 226
      api.go
  2. 56
      api_test.go
  3. 27
      impl.go

226
api.go

@ -22,6 +22,8 @@ import (
const headerRequestId = "X-Request-Id"
const headerServiceKey = "X-Service-Key"
const tokenInterval = 1 * time.Minute
const constOperationDelete = "delete"
const constOperationAdd = "add"
type api struct {
url string
@ -43,6 +45,8 @@ type Obj interface {
ObjDelete(ctx context.Context, uids string) (result models.ResponseData, err error)
ObjAttrUpdate(ctx context.Context, uid, name, value, src, editor string) (result models.ResponseData, err error)
LinkGet(ctx context.Context, tpl, obj, mode, short string) (result models.ResponseData, err error)
LinkAdd(ctx context.Context, element, from, to string) (result models.ResponseData, err error)
LinkDelete(ctx context.Context, element, from, to string) (result models.ResponseData, err error)
LinkGetWithCache(ctx context.Context, tpl, obj, mode, short string) (result models.ResponseData, err error)
Query(ctx context.Context, query, method, bodyJSON string) (result string, err error)
Search(ctx context.Context, query, method, bodyJSON string) (resp string, err error)
@ -53,7 +57,10 @@ type Obj interface {
// Query результат выводим в объект как при вызове Curl
func (a *api) Query(ctx context.Context, query, method, bodyJSON string) (result string, err error) {
//_, err = a.cb.Execute(func() (interface{}, error) {
result, err = a.query(ctx, query, method, bodyJSON)
//return result, err
//})
if err != nil {
logger.Error(ctx, "error UpdateFilter primary haproxy", zap.Error(err))
return "", fmt.Errorf("error request Query (primary route). err: %s", err)
@ -94,14 +101,19 @@ func (a *api) QueryWithCache(ctx context.Context, query, method, bodyJSON string
res, err = a.Query(ctx, query, method, bodyJSON)
return res, err
}, a.cacheUpdateInterval)
if err != nil {
return "", fmt.Errorf("error from cache update. err: %s", err)
}
if value == nil {
return "", fmt.Errorf("returned result from cache update is empty")
if err == nil && value != nil {
return fmt.Sprint(value), nil
} else {
err = fmt.Errorf("error exec cache query (Query). err: %s, value is empty: %t, value: %+v", err, value == nil, value)
}
}
return fmt.Sprint(value), err
if err != nil {
logger.Error(ctx, "error exec cache query", zap.String("func", "QueryWithCache"), zap.String("key", key), zap.Error(err))
cacheValue, err = a.Query(ctx, query, method, bodyJSON)
if err != nil {
return result, fmt.Errorf("error get cache (Query). err: %s", err)
}
}
return fmt.Sprint(cacheValue), err
@ -111,8 +123,10 @@ func (a *api) ObjGet(ctx context.Context, uids string) (result models.ResponseDa
if uids == "" {
return result, fmt.Errorf("error ObjGet. uids is empty")
}
//_, err = a.cb.Execute(func() (interface{}, error) {
result, err = a.objGet(ctx, uids)
//return result, err
//})
if err != nil {
logger.Error(ctx, "error ObjGet primary haproxy", zap.Error(err))
return result, fmt.Errorf("error request ObjGet (primary route). err: %s", err)
@ -122,16 +136,6 @@ func (a *api) ObjGet(ctx context.Context, uids string) (result models.ResponseDa
}
func (a *api) ObjGetWithCache(ctx context.Context, uids string) (result *models.ResponseData, err error) {
//t, e := a.ObjGet(ctx, uids)
//return &t, e
//t := time.Now()
//defer func() {
// fmt.Printf("\nDEFER Время выполнения общее ObjGetWithCache: %fc\n", time.Since(t).Seconds())
//}()
var ok bool
var handlers = map[string]string{}
handlers[headerRequestId] = logger.GetRequestIDCtx(ctx)
if a.observeLog {
@ -140,7 +144,6 @@ func (a *api) ObjGetWithCache(ctx context.Context, uids string) (result *models.
key := lib.Hash(uids)
cacheValue, err := cache.Cache().Get(key)
//fmt.Printf("\nберем объект из кеша. cacheValue uids: %s len %s, время: %fc, err: %s, reqID: %s", uids, len(fmt.Sprint(cacheValue)), time.Since(t).Seconds(), err, logger.GetRequestIDCtx(ctx))
if errors.Is(err, cache.ErrorKeyNotFound) {
var value interface{}
@ -148,35 +151,89 @@ func (a *api) ObjGetWithCache(ctx context.Context, uids string) (result *models.
res, err = a.ObjGet(ctx, uids)
return res, err
}, a.cacheUpdateInterval)
if err != nil {
return nil, fmt.Errorf("error from cache update. err: %s", err)
}
if value == nil {
return nil, fmt.Errorf("returned result from cache update is empty")
if err == nil && value != nil {
res, ok := value.(models.ResponseData)
if ok {
return &res, nil
}
err = fmt.Errorf("error cast type in cache query (ObjGetWithCache). err: %s, value is empty: %t, result: %+v", err, value == nil, value)
} else {
err = fmt.Errorf("error exec cache query (ObjGet). err: %s, value is empty: %t", err, value == nil)
}
}
res, ok := value.(models.ResponseData)
if !ok {
err = fmt.Errorf("[ObjGetWithCache] error. cast type (ResponseData) is fail for cache.ErrorKeyNotFound. result: %+v", value)
// повторяем запрос (без кеша)
if err != nil {
logger.Error(ctx, "error exec cache query", zap.String("func", "ObjGetWithCache"), zap.String("key", key), zap.Error(err))
cacheValue, err = a.ObjGet(ctx, uids)
if err == nil && cacheValue != nil {
res, ok := cacheValue.(models.ResponseData)
if ok {
return &res, nil
}
err = fmt.Errorf("error cast type in query (ObjGet). err: %s, value is empty: %t, result: %+v", err, cacheValue == nil, cacheValue)
} else {
err = fmt.Errorf("error exec query (ObjGet). err: %s, value is empty: %t", err, cacheValue == nil)
}
}
return &res, err
if err == nil && cacheValue != nil {
res, ok := cacheValue.(models.ResponseData)
if ok {
return &res, nil
}
err = fmt.Errorf("error cast type in query (ObjGet). err: %s, value is empty: %t, result: %+v", err, cacheValue == nil, cacheValue)
} else {
err = fmt.Errorf("error exec query (ObjGet). err: %s, value is empty: %t", err, cacheValue == nil)
}
res, ok := cacheValue.(models.ResponseData)
if !ok {
return result, fmt.Errorf("[ObjGetWithCache] error. cast type (ResponseData) is fail. result: %+v", cacheValue)
return result, err
}
// LinkDelete - удаление линки
func (a *api) LinkDelete(ctx context.Context, element, from, to string) (result models.ResponseData, err error) {
//_, err = a.cb.Execute(func() (interface{}, error) {
result, err = a.linkOperation(ctx, constOperationDelete, element, from, to)
//return result, err
//})
if err != nil {
logger.Error(ctx, "error LinkDelete primary haproxy",
zap.String("operation", constOperationDelete),
zap.String("element", element),
zap.String("from", from),
zap.String("to", to))
//zap.Any("status CircuitBreaker", a.cb.State().String()), zap.Error(err))
return result, fmt.Errorf("error request LinkDelete (primary route). check apiCircuitBreaker. err: %s", err)
}
//fmt.Printf("\nберем объект из кеша. общее время: %fc, err: %s reqID: %s\n\n", time.Since(t).Seconds(), err, logger.GetRequestIDCtx(ctx))
return result, err
}
// LinkAdd - добавление линки в объект
func (a *api) LinkAdd(ctx context.Context, element, from, to string) (result models.ResponseData, err error) {
//_, err = a.cb.Execute(func() (interface{}, error) {
result, err = a.linkOperation(ctx, constOperationAdd, element, from, to)
//return result, err
//})
if err != nil {
logger.Error(ctx, "error LinkAdd primary haproxy",
zap.String("operation", constOperationAdd),
zap.String("element", element),
zap.String("from", from),
zap.String("to", to))
//zap.Any("status CircuitBreaker", a.cb.State().String()), zap.Error(err))
return result, fmt.Errorf("error request LinkAdd (primary route). check apiCircuitBreaker. err: %s", err)
}
return &res, err
return result, err
}
// LinkGet - получение связанных объектов
func (a *api) LinkGet(ctx context.Context, tpl, obj, mode, short string) (result models.ResponseData, err error) {
//_, err = a.cb.Execute(func() (interface{}, error) {
result, err = a.linkGet(ctx, tpl, obj, mode, short)
//return result, err
//})
if err != nil {
logger.Error(ctx, "error LinkGet primary haproxy", zap.Error(err))
return result, fmt.Errorf("error request LinkGet (primary route). err: %s", err)
@ -188,9 +245,6 @@ func (a *api) LinkGet(ctx context.Context, tpl, obj, mode, short string) (result
// LinkGetWithCache - получение связанных объектов
// (с кешем если задан TTL кеширования при инициализации кеша)
func (a *api) LinkGetWithCache(ctx context.Context, tpl, obj, mode, short string) (result models.ResponseData, err error) {
//return a.LinkGet(ctx, tpl, obj, mode, short)
var ok bool
var handlers = map[string]string{}
handlers[headerRequestId] = logger.GetRequestIDCtx(ctx)
@ -207,24 +261,40 @@ func (a *api) LinkGetWithCache(ctx context.Context, tpl, obj, mode, short string
res, err = a.LinkGet(ctx, tpl, obj, mode, short)
return res, err
}, a.cacheUpdateInterval)
if err != nil {
return result, fmt.Errorf("error from cache update. err: %s", err)
}
if value == nil {
return result, fmt.Errorf("returned result from cache update is empty")
if err == nil && value != nil {
result, ok = value.(models.ResponseData)
if ok {
return result, nil
}
err = fmt.Errorf("error cast type in cache query (LinkGetWithCache). err: %s, value is empty: %t, result: %+v", err, value == nil, value)
} else {
err = fmt.Errorf("error exec cache query (LinkGet). err: %s, value is empty: %t", err, value == nil)
}
}
result, ok = value.(models.ResponseData)
if !ok {
err = fmt.Errorf("[LinkGetWithCache] error. cast type (ResponseData) is fail. result: %+v", value)
// повторяем запрос (без кеша)
if err != nil {
logger.Error(ctx, "error exec cache query", zap.String("func", "LinkGetWithCache"), zap.String("key", key), zap.Error(err))
cacheValue, err = a.LinkGet(ctx, tpl, obj, mode, short)
if err == nil && cacheValue != nil {
res, ok := cacheValue.(models.ResponseData)
if ok {
return res, nil
}
err = fmt.Errorf("error cast type in query (LinkGet). err: %s, value is empty: %t, result: %+v", err, cacheValue == nil, cacheValue)
} else {
err = fmt.Errorf("error exec query (LinkGet). err: %s, value is empty: %t", err, cacheValue == nil)
}
return result, err
}
result, ok = cacheValue.(models.ResponseData)
if !ok {
return result, fmt.Errorf("[LinkGetWithCache] error. cast type (ResponseData) is fail. result: %+v", cacheValue)
if err == nil && cacheValue != nil {
res, ok := cacheValue.(models.ResponseData)
if ok {
return res, nil
}
err = fmt.Errorf("error cast type in query (ObjGet). err: %s, value is empty: %t, result: %+v", err, cacheValue == nil, cacheValue)
} else {
err = fmt.Errorf("error exec query (ObjGet). err: %s, value is empty: %t", err, cacheValue == nil)
}
return result, err
@ -235,8 +305,10 @@ func (a *api) ObjAttrUpdate(ctx context.Context, uid, name, value, src, editor s
if uid == "" {
return result, fmt.Errorf("[ObjAttrUpdate] error ObjAttrUpdate. uid is empty")
}
//_, err = a.cb.Execute(func() (interface{}, error) {
result, err = a.objAttrUpdate(ctx, uid, name, value, src, editor)
//return result, err
//})
if err != nil {
logger.Error(ctx, "error ObjAttrUpdate primary haproxy", zap.Error(err))
return result, fmt.Errorf("[ObjAttrUpdate] error request ObjAttrUpdate (primary route). err: %s", err)
@ -256,7 +328,10 @@ func (a *api) ObjAttrUpdate(ctx context.Context, uid, name, value, src, editor s
// all (elements) - Получаем поля, по заданному в параметрах типу
// "" - без действия - получаем все поля для объекта
func (a *api) Element(ctx context.Context, action, body string) (result models.ResponseData, err error) {
//_, err = a.cb.Execute(func() (interface{}, error) {
result, err = a.element(ctx, action, body)
//return result, err
//})
if err != nil {
logger.Error(ctx, "error Element primary haproxy", zap.Error(err))
return result, fmt.Errorf("[Element] error request Element (primary route). err: %s", err)
@ -292,31 +367,53 @@ func (a *api) ElementWithCache(ctx context.Context, action, body string) (result
res, err = a.Element(ctx, action, body)
return res, err
}, a.cacheUpdateInterval)
if err != nil {
return result, fmt.Errorf("error from cache update. err: %s", err)
}
if value == nil {
return result, fmt.Errorf("returned result from cache update is empty")
if err == nil && value != nil {
result, ok = value.(models.ResponseData)
if ok {
return result, nil
}
err = fmt.Errorf("error cast type in cache query (ElementWithCache). err: %s, value is empty: %t, result: %+v", err, value == nil, value)
} else {
err = fmt.Errorf("error exec cache query. err: %s, value is empty: %t", err, value == nil)
}
}
result, ok = value.(models.ResponseData)
if !ok {
err = fmt.Errorf("[ElementWithCache] error. cast type (ResponseData) is fail. result: %+v", value)
// повторяем запрос (без кеша)
if err != nil {
logger.Error(ctx, "error exec cache query", zap.String("func", "ElementWithCache"), zap.String("key", key), zap.Error(err))
cacheValue, err = a.Element(ctx, action, body)
if err == nil && cacheValue != nil {
res, ok := cacheValue.(models.ResponseData)
if ok {
return res, nil
}
err = fmt.Errorf("error cast type in query (Element). err: %s, value is empty: %t, result: %+v", err, cacheValue == nil, cacheValue)
} else {
err = fmt.Errorf("error exec query (Element). err: %s, value is empty: %t", err, cacheValue == nil)
}
return result, err
}
result, ok = cacheValue.(models.ResponseData)
if !ok {
return result, fmt.Errorf("[ElementWithCache] error. cast type (ResponseData) is fail. result: %+v", cacheValue)
if err == nil && cacheValue != nil {
res, ok := cacheValue.(models.ResponseData)
if ok {
return res, nil
}
err = fmt.Errorf("error cast type in query (ObjGet). err: %s, value is empty: %t, result: %+v", err, cacheValue == nil, cacheValue)
} else {
err = fmt.Errorf("error exec query (ObjGet). err: %s, value is empty: %t", err, cacheValue == nil)
}
return result, err
}
func (a *api) ObjCreate(ctx context.Context, bodymap map[string]string) (result models.ResponseData, err error) {
//_, err = a.cb.Execute(func() (interface{}, error) {
result, err = a.objCreate(ctx, bodymap)
//if err != nil {
// err = fmt.Errorf("error ObjCreate, bodymap: %+v, err: %s)", bodymap, err)
//}
//return result, err
//})
if err != nil {
logger.Error(ctx, "error ObjCreate primary haproxy", zap.Error(err), zap.Any("bodymap", bodymap))
return result, fmt.Errorf("error request ObjCreate (primary route). err: %s", err)
@ -326,7 +423,10 @@ func (a *api) ObjCreate(ctx context.Context, bodymap map[string]string) (result
}
func (a *api) ObjDelete(ctx context.Context, uids string) (result models.ResponseData, err error) {
//_, err = a.cb.Execute(func() (interface{}, error) {
result, err = a.objDelete(ctx, uids)
//return result, err
//})
if err != nil {
logger.Error(ctx, "error ObjDelete primary haproxy", zap.Error(err))
return result, fmt.Errorf("error request ObjDelete (primary route). err: %s", err)

56
api_test.go

@ -187,6 +187,7 @@ func TestApi_Search(t *testing.T) {
cfg.CbInterval = 5 * time.Second
cfg.ApiCacheTTL = 10 * time.Second
cfg.LogboxEndpoint = "http://127.0.0.1:8999"
cfg.CbMaxRequestsLogbox = 3
cfg.CbTimeoutLogbox = 5 * time.Second
cfg.CbIntervalLogbox = 5 * time.Second
@ -232,3 +233,58 @@ func TestApi_Search(t *testing.T) {
return
}
func Test_ObjAdd(t *testing.T) {
var err error
ctx := context.Background()
uids := "2019-12-25T14-27-21Z-ab85d7"
element := "access_admin"
to := "7929d995-3206-d127-fa4a-1e6950eaaa22"
cfg := config
cfg.UrlApi = "https://lms.wb.ru/lms/api"
cfg.CbMaxRequests = 3
cfg.CbTimeout = 5 * time.Second
cfg.CbInterval = 5 * time.Second
cfg.ApiCacheTTL = 5 * time.Second
cfg.LogboxEndpoint = "127.0.0.1:8999"
cfg.CbMaxRequestsLogbox = 3
cfg.CbTimeoutLogbox = 5 * time.Second
cfg.CbIntervalLogbox = 5 * time.Second
err = logger.SetupDefaultLogboxLogger("api/client", logger.LogboxConfig{
Endpoint: cfg.LogboxEndpoint,
AccessKeyID: cfg.LogboxAccessKeyId,
SecretKey: cfg.LogboxSecretKey,
RequestTimeout: cfg.LogboxRequestTimeout,
CbMaxRequests: cfg.CbMaxRequestsLogbox,
CbTimeout: cfg.CbTimeoutLogbox,
CbInterval: cfg.CbIntervalLogbox,
}, map[string]string{
logger.ServiceIDKey: lib.Hash(lib.UUID()),
logger.ConfigIDKey: "api",
logger.ServiceTypeKey: "api",
})
if err != nil {
fmt.Println("error init logger")
}
apiClient := New(
ctx,
cfg.UrlApi,
true,
cfg.ApiCacheTTL,
cfg.CbMaxRequests,
cfg.CbTimeout,
cfg.CbInterval,
"LKHlhb899Y09olUi",
)
fmt.Println("1. добавление связи")
res, err := apiClient.LinkAdd(ctx, uids, element, to)
fmt.Println(res, err)
return
}

27
impl.go

@ -112,6 +112,33 @@ func (a *api) linkGet(ctx context.Context, tpl, obj, mode, short string) (result
return result, err
}
func (a *api) linkOperation(ctx context.Context, operation, element, from, to string) (result models.ResponseData, err error) {
var handlers = map[string]string{}
token, err := lib.GenXServiceKey(a.domain, []byte(a.projectKey), tokenInterval)
if err != nil {
return result, fmt.Errorf("error GenXServiceKey. err: %s", err)
}
handlers[headerServiceKey] = token
if a.observeLog {
defer a.observeLogger(ctx, time.Now(), "linkAdd", err, element, from, to)
}
urlc := a.url + "/link/" + operation + "?element=" + element + "&from=" + from + "&to=" + to
urlc = strings.Replace(urlc, "//link", "/link", 1)
if operation != "add" && operation != "delete" {
err = fmt.Errorf("operation '%s' is not resolved. (url: %s)", operation, urlc)
return result, err
}
_, err = lib.Curl(ctx, "GET", urlc, "", &result, handlers, nil)
if err != nil {
err = fmt.Errorf("%s (url: %s)", err, urlc)
}
return result, err
}
// ObjAttrUpdate изменение значения аттрибута объекта
func (a *api) objAttrUpdate(ctx context.Context, uid, name, value, src, editor string) (result models.ResponseData, err error) {
var handlers = map[string]string{}

Loading…
Cancel
Save