diff --git a/pkg/clients/middleware/caching_middleware.go b/pkg/clients/middleware/caching_middleware.go index 370061ccc247735763395c3f6a1ebeb22804f2fb..0dd4f15b4e24affb13562c57a1d69b0e3adce33d 100644 --- a/pkg/clients/middleware/caching_middleware.go +++ b/pkg/clients/middleware/caching_middleware.go @@ -6,6 +6,7 @@ import ( "git.perx.ru/perxis/perxis-go/pkg/cache" service "git.perx.ru/perxis/perxis-go/pkg/clients" + "git.perx.ru/perxis/perxis-go/pkg/data" ) func makeKey(ss ...string) string { @@ -40,7 +41,7 @@ func (m cachingMiddleware) Get(ctx context.Context, spaceId string, id string) ( key := makeKey(spaceId, id) value, e := m.cache.Get(key) if e == nil { - return value.(*service.Client), err + return value.(*service.Client).Clone(), nil } cl, err = m.next.Get(ctx, spaceId, id) if err == nil { @@ -48,8 +49,9 @@ func (m cachingMiddleware) Get(ctx context.Context, spaceId string, id string) ( for _, key := range keysFromIdentities(spaceId, cl) { _ = m.cache.Set(key, cl) } + return cl.Clone(), nil } - return cl, err + return nil, err } func (m cachingMiddleware) GetBy(ctx context.Context, spaceId string, params *service.GetByParams) (cl *service.Client, err error) { @@ -60,7 +62,7 @@ func (m cachingMiddleware) GetBy(ctx context.Context, spaceId string, params *se key := getIdentKey(spaceId, params) value, e := m.cache.Get(key) if e == nil { - return value.(*service.Client), err + return value.(*service.Client).Clone(), nil } cl, err = m.next.GetBy(ctx, spaceId, params) if err == nil { @@ -68,21 +70,23 @@ func (m cachingMiddleware) GetBy(ctx context.Context, spaceId string, params *se for _, key := range keysFromIdentities(spaceId, cl) { _ = m.cache.Set(key, cl) } + return cl.Clone(), nil } - return cl, err + return nil, err } func (m cachingMiddleware) List(ctx context.Context, spaceId string) (clients []*service.Client, err error) { value, e := m.cache.Get(spaceId) if e == nil { - return value.([]*service.Client), err + return data.CloneSlice(value.([]*service.Client)), nil } clients, err = m.next.List(ctx, spaceId) if err == nil { _ = m.cache.Set(spaceId, clients) + return data.CloneSlice(clients), nil } - return clients, err + return nil, err } func (m cachingMiddleware) Update(ctx context.Context, client *service.Client) (err error) { diff --git a/pkg/clients/middleware/caching_middleware_test.go b/pkg/clients/middleware/caching_middleware_test.go index 02129d1772406b0d33f693d2d10ae5bc008492d7..821d2cb29579029f10e1726291212b6ccaeaceae 100644 --- a/pkg/clients/middleware/caching_middleware_test.go +++ b/pkg/clients/middleware/caching_middleware_test.go @@ -40,11 +40,13 @@ func TestClientsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, cltID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша, после повторного запроса.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша, после повторного запроса.") + assert.NotSame(t, v1, v2) v3, err := svc.GetBy(ctx, spaceID, &clients.GetByParams{OAuthClientID: clientID}) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кэша при запросе по ClientID.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кэша при запросе по ClientID.") + assert.NotSame(t, v2, v3) cs.AssertExpectations(t) }) @@ -61,11 +63,13 @@ func TestClientsCache(t *testing.T) { v2, err := svc.GetBy(ctx, spaceID, &clients.GetByParams{OAuthClientID: clientID}) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша, после повторного запроса.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша, после повторного запроса.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, cltID) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кэша, после запроса Get.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кэша, после запроса Get.") + assert.NotSame(t, v2, v3) cs.AssertExpectations(t) }) @@ -82,7 +86,8 @@ func TestClientsCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.NotSame(t, vl1[0], vl2[0]) cs.AssertExpectations(t) }) @@ -102,11 +107,13 @@ func TestClientsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, cltID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) v3, err := svc.GetBy(ctx, spaceID, &clients.GetByParams{OAuthClientID: clientID}) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кэша по ClientID.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кэша по ClientID.") + assert.NotSame(t, v2, v3) vl1, err := svc.List(ctx, spaceID) require.NoError(t, err) @@ -114,7 +121,8 @@ func TestClientsCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) assert.Len(t, vl2, 1) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.NotSame(t, vl1[0], vl2[0]) cs.On("Update", mock.Anything, mock.Anything).Return(nil).Once() @@ -126,16 +134,17 @@ func TestClientsCache(t *testing.T) { vl3, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидается получение объектов из кэша, после повторного запроса.") v4, err := svc.Get(ctx, spaceID, cltID) require.NoError(t, err) - assert.NotSame(t, v2, v4, "Ожидает что после обновления объект был удален из кэша и будет запрошен заново из сервиса.") + assert.NotEqual(t, v2, v4, "Ожидает что после обновления объект был удален из кэша и будет запрошен заново из сервиса.") v5, err := svc.GetBy(ctx, spaceID, &clients.GetByParams{OAuthClientID: clientID}) require.NoError(t, err) - assert.NotSame(t, v3, v5) - assert.Same(t, v4, v5, "Ожидается что после обновления объект был удален из кеша и после запроса Get в кеш попал объект запрошенный заново из сервиса.") + assert.NotEqual(t, v3, v5) + assert.Equal(t, v4, v5, "Ожидается что после обновления объект был удален из кеша и после запроса Get в кеш попал объект запрошенный заново из сервиса.") + assert.NotSame(t, v4, v5) cs.AssertExpectations(t) }) @@ -153,7 +162,8 @@ func TestClientsCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) assert.Len(t, vl2, 1) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.NotSame(t, vl1[0], vl2[0]) cs.On("Update", mock.Anything, mock.Anything).Return(nil).Once() @@ -164,7 +174,7 @@ func TestClientsCache(t *testing.T) { vl3, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидается получение объектов из кэша, после повторного запроса.") cs.AssertExpectations(t) }) @@ -182,18 +192,21 @@ func TestClientsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, cltID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) v3, err := svc.GetBy(ctx, spaceID, &clients.GetByParams{OAuthClientID: clientID}) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кэша по ClientID.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кэша по ClientID.") + assert.NotSame(t, v2, v3) vl1, err := svc.List(ctx, spaceID) require.NoError(t, err) vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.NotSame(t, vl1[0], vl2[0]) cs.On("Delete", mock.Anything, spaceID, cltID).Return(nil).Once() @@ -231,7 +244,8 @@ func TestClientsCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.NotSame(t, vl1[0], vl2[0]) cs.On("Delete", mock.Anything, spaceID, cltID).Return(nil).Once() @@ -259,7 +273,8 @@ func TestClientsCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.NotSame(t, vl1[0], vl2[0]) assert.Len(t, vl2, 1, "Ожидается получение объектов из кэша.") cs.On("Create", mock.Anything, mock.Anything).Return(&clients.Client{ID: "cltID2", SpaceID: spaceID, Name: "client_2"}, nil).Once() @@ -290,18 +305,21 @@ func TestClientsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, cltID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) v3, err := svc.GetBy(ctx, spaceID, &clients.GetByParams{OAuthClientID: clientID}) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кэша по ClientID.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кэша по ClientID.") + assert.NotSame(t, v2, v3) vl1, err := svc.List(ctx, spaceID) require.NoError(t, err) vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.NotSame(t, vl1[0], vl2[0]) cs.On("Enable", mock.Anything, spaceID, cltID, tr).Return(nil).Once() @@ -314,15 +332,15 @@ func TestClientsCache(t *testing.T) { v4, err := svc.Get(ctx, spaceID, cltID) require.NoError(t, err) - assert.NotSame(t, v2, v4, "Ожидается что после активации объект был удален из кэша и запрошен у сервиса.") + assert.NotEqual(t, v2, v4, "Ожидается что после активации объект был удален из кэша и запрошен у сервиса.") v5, err := svc.GetBy(ctx, spaceID, &clients.GetByParams{OAuthClientID: clientID}) require.NoError(t, err) - assert.NotSame(t, v3, v5, "Ожидается что после активации объект был удален из кеша и после запроса Get в кеш попал объект запрошенный заново из сервиса.") + assert.NotEqual(t, v3, v5, "Ожидается что после активации объект был удален из кеша и после запроса Get в кеш попал объект запрошенный заново из сервиса.") vl3, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидается что после активации объекта, кеш будет очищен и объекты будут запрошены заново из сервиса.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидается что после активации объекта, кеш будет очищен и объекты будут запрошены заново из сервиса.") cs.AssertExpectations(t) }) @@ -340,7 +358,8 @@ func TestClientsCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша, после повторного запроса.") + assert.NotSame(t, vl1[0], vl2[0]) cs.On("Enable", mock.Anything, spaceID, cltID, tr).Return(nil).Once() @@ -352,7 +371,7 @@ func TestClientsCache(t *testing.T) { vl3, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидается что после активации объекта, кеш будет очищен и объекты будут запрошены заново из сервиса.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидается что после активации объекта, кеш будет очищен и объекты будут запрошены заново из сервиса.") cs.AssertExpectations(t) }) @@ -369,13 +388,16 @@ func TestClientsCache(t *testing.T) { require.NoError(t, err) v2, err := svc.Get(ctx, spaceID, cltID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша после повторного запроса.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша после повторного запроса.") + assert.NotSame(t, v1, v2) time.Sleep(2 * ttl) v3, err := svc.Get(ctx, spaceID, cltID) require.NoError(t, err) assert.NotSame(t, v2, v3, "Ожидается что элемент был удален из кэша по истечению ttl и будет запрошен заново из сервиса.") + assert.Equal(t, v2, v3) + assert.NotSame(t, v2, v3) cs.AssertExpectations(t) }) diff --git a/pkg/collaborators/collaborator.go b/pkg/collaborators/collaborator.go index 701d8e85b578dafc2036c281c204720080412ac5..5fe1b481c231568af13b9c9e827eede723312576 100644 --- a/pkg/collaborators/collaborator.go +++ b/pkg/collaborators/collaborator.go @@ -5,3 +5,11 @@ type Collaborator struct { Subject string `bson:"subject"` Role string `bson:"role"` } + +func (c Collaborator) Clone() *Collaborator { + return &Collaborator{ + SpaceID: c.SpaceID, + Subject: c.Subject, + Role: c.Role, + } +} diff --git a/pkg/collaborators/middleware/caching_middleware.go b/pkg/collaborators/middleware/caching_middleware.go index 25ae89c46c7863f2143d17850513e88f1d4b68b0..7faeb638b0ca2bb673de4852c21e75b7f1f9afc7 100644 --- a/pkg/collaborators/middleware/caching_middleware.go +++ b/pkg/collaborators/middleware/caching_middleware.go @@ -6,6 +6,7 @@ import ( "git.perx.ru/perxis/perxis-go/pkg/cache" service "git.perx.ru/perxis/perxis-go/pkg/collaborators" + "git.perx.ru/perxis/perxis-go/pkg/data" ) func makeKey(ss ...string) string { @@ -65,24 +66,26 @@ func (m cachingMiddleware) ListCollaborators(ctx context.Context, spaceId string value, e := m.cache.Get(spaceId) if e == nil { - return value.([]*service.Collaborator), err + return data.CloneSlice(value.([]*service.Collaborator)), nil } collaborators, err = m.next.ListCollaborators(ctx, spaceId) if err == nil { _ = m.cache.Set(spaceId, collaborators) + return data.CloneSlice(collaborators), nil } - return collaborators, err + return nil, err } func (m cachingMiddleware) ListSpaces(ctx context.Context, subject string) (collaborators []*service.Collaborator, err error) { value, e := m.cache.Get(subject) if e == nil { - return value.([]*service.Collaborator), err + return data.CloneSlice(value.([]*service.Collaborator)), nil } collaborators, err = m.next.ListSpaces(ctx, subject) if err == nil { _ = m.cache.Set(subject, collaborators) + return data.CloneSlice(collaborators), nil } - return collaborators, err + return nil, err } diff --git a/pkg/collaborators/middleware/caching_middleware_test.go b/pkg/collaborators/middleware/caching_middleware_test.go index 2e453ae67ca574fc6a7ec54dbdb0df88bdd358d2..6b96d0a8ff65dcc56d3139e2b99eac28720bb364 100644 --- a/pkg/collaborators/middleware/caching_middleware_test.go +++ b/pkg/collaborators/middleware/caching_middleware_test.go @@ -56,7 +56,8 @@ func TestCollaboratorsCache(t *testing.T) { require.NoError(t, err) v2, err := svc.ListCollaborators(ctx, spaceID) require.NoError(t, err) - assert.Same(t, v1[0], v2[0], "Ожидается получение объектов из кэша при повторном запросе.") + assert.Equal(t, v1[0], v2[0], "Ожидается получение объектов из кэша при повторном запросе.") + assert.NotSame(t, v1[0], v2[0]) cs.AssertExpectations(t) }) @@ -72,7 +73,8 @@ func TestCollaboratorsCache(t *testing.T) { require.NoError(t, err) v2, err := svc.ListSpaces(ctx, userID) require.NoError(t, err) - assert.Same(t, v1[0], v2[0], "Ожидается получение объектов из кэша при повторном запросе.") + assert.Equal(t, v1[0], v2[0], "Ожидается получение объектов из кэша при повторном запросе.") + assert.NotSame(t, v1[0], v2[0]) cs.AssertExpectations(t) }) @@ -98,13 +100,15 @@ func TestCollaboratorsCache(t *testing.T) { require.NoError(t, err) lc2, err := svc.ListCollaborators(ctx, spaceID) require.NoError(t, err) - assert.Same(t, lc1[0], lc2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, lc1[0], lc2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, lc1[0], lc2[0]) ls1, err := svc.ListSpaces(ctx, userID) require.NoError(t, err) ls2, err := svc.ListSpaces(ctx, userID) require.NoError(t, err) - assert.Same(t, ls1[0], ls2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, ls1[0], ls2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, ls1[0], ls2[0]) cs.On("Remove", mock.Anything, spaceID, userID).Return(nil).Once() @@ -153,13 +157,15 @@ func TestCollaboratorsCache(t *testing.T) { require.NoError(t, err) lc2, err := svc.ListCollaborators(ctx, spaceID) require.NoError(t, err) - assert.Same(t, lc1[0], lc2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, lc1[0], lc2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, lc1[0], lc2[0]) ls1, err := svc.ListSpaces(ctx, userID) require.NoError(t, err) ls2, err := svc.ListSpaces(ctx, userID) require.NoError(t, err) - assert.Same(t, ls1[0], ls2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, ls1[0], ls2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, ls1[0], ls2[0]) cs.On("Remove", mock.Anything, spaceID, userID).Return(nil).Once() diff --git a/pkg/collections/middleware/caching_middleware.go b/pkg/collections/middleware/caching_middleware.go index 0e329e801c4e0d7eeb6939d3fed857c023cbbc8a..cb95d0d9a8772f91700f5f630fa9bb2631e51937 100644 --- a/pkg/collections/middleware/caching_middleware.go +++ b/pkg/collections/middleware/caching_middleware.go @@ -44,7 +44,7 @@ func (m cachingMiddleware) Get(ctx context.Context, spaceId string, envId string opts := service.MergeGetOptions(options...) value, e := m.cache.Get(makeKey(spaceId, envId, collectionId, opts.DisableSchemaIncludes)) if e == nil { - return value.(*service.Collection), err + return value.(*service.Collection).Clone(), nil } coll, err = m.next.Get(ctx, spaceId, envId, collectionId, options...) if err == nil { @@ -56,9 +56,9 @@ func (m cachingMiddleware) Get(ctx context.Context, spaceId string, envId string for _, al := range env.Aliases { _ = m.cache.Set(makeKey(coll.SpaceID, al, coll.ID, opts.DisableSchemaIncludes), coll) } - + return coll.Clone(), nil } - return coll, err + return nil, err } func (m cachingMiddleware) List(ctx context.Context, spaceId, envId string, filter *service.Filter) (collections []*service.Collection, err error) { diff --git a/pkg/collections/middleware/caching_middleware_test.go b/pkg/collections/middleware/caching_middleware_test.go index ac284ce5464af7469fee9ad4a7babf377b9c335a..24646008ba32736ca45f7bcdc7e0a4845c43877d 100644 --- a/pkg/collections/middleware/caching_middleware_test.go +++ b/pkg/collections/middleware/caching_middleware_test.go @@ -46,11 +46,13 @@ func TestCollections_Cache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кеша при повторном запросе по ID окружения.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кеша при повторном запросе по ID окружения.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envAlias, colID) require.NoError(t, err) - assert.Same(t, v3, v2, "Ожидается получение объекта из кеша, при запросе того же объекта по alias окружения.") + assert.Equal(t, v3, v2, "Ожидается получение объекта из кеша, при запросе того же объекта по alias окружения.") + assert.NotSame(t, v3, v2) env.AssertExpectations(t) col.AssertExpectations(t) @@ -70,11 +72,13 @@ func TestCollections_Cache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envAlias, colID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кеша при повторном запросе по Alias окружения.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кеша при повторном запросе по Alias окружения.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) - assert.Same(t, v3, v2, "Ожидается получение объекта из кеша, при запросе того же объекта по ID окружения.") + assert.Equal(t, v3, v2, "Ожидается получение объекта из кеша, при запросе того же объекта по ID окружения.") + assert.NotSame(t, v3, v2) env.AssertExpectations(t) col.AssertExpectations(t) @@ -115,12 +119,12 @@ func TestCollections_Cache(t *testing.T) { // vl2, err := svc.List(ctx, spaceID, envID, nil) // require.NoError(t, err) // assert.Len(t, vl2, 1) - // assert.Same(t, vl1[0], vl2[0], "При повторном запросе по ID окружения, ожидается получение списка объектов из кеша.") + // assert.Equal(t, vl1[0], vl2[0], "При повторном запросе по ID окружения, ожидается получение списка объектов из кеша.") // // vl3, err := svc.List(ctx, spaceID, envAlias, nil) // require.NoError(t, err) // assert.Len(t, vl3, 1) - // assert.Same(t, vl3[0], vl2[0], "При повторном запросе по Alias окружения, ожидается получение списка объектов из кеша.") + // assert.Equal(t, vl3[0], vl2[0], "При повторном запросе по Alias окружения, ожидается получение списка объектов из кеша.") // // env.AssertExpectations(t) // col.AssertExpectations(t) @@ -161,11 +165,13 @@ func TestCollections_Cache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кеша по ID окружения.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кеша по ID окружения.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envAlias, colID) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кеша по Alias окружения.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кеша по Alias окружения.") + assert.NotSame(t, v2, v3) vl1, err := svc.List(ctx, spaceID, envID, nil) require.NoError(t, err) @@ -181,15 +187,16 @@ func TestCollections_Cache(t *testing.T) { v4, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) - assert.NotSame(t, v3, v4, "Ожидает что элемент после обновления был удален из кэша и будет запрошен заново из сервиса.") + assert.NotEqual(t, v3, v4, "Ожидает что элемент после обновления был удален из кэша и будет запрошен заново из сервиса.") v5, err := svc.Get(ctx, spaceID, envAlias, colID) require.NoError(t, err) - assert.Same(t, v4, v5, "Ожидается получение объекта из кеша по Alias окружения.") + assert.Equal(t, v4, v5, "Ожидается получение объекта из кеша по Alias окружения.") + assert.NotSame(t, v4, v5) vl2, err := svc.List(ctx, spaceID, envID, nil) require.NoError(t, err) - assert.NotSame(t, vl1[0], vl2[0], "Ожидает что после обновления элементы будут запрошены заново из сервиса.") + assert.NotEqual(t, vl1[0], vl2[0], "Ожидает что после обновления элементы будут запрошены заново из сервиса.") env.AssertExpectations(t) col.AssertExpectations(t) @@ -212,11 +219,13 @@ func TestCollections_Cache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envAlias, colID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кеша по Alias окружения.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кеша по Alias окружения.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кеша по ID окружения.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кеша по ID окружения.") + assert.NotSame(t, v2, v3) vl1, err := svc.List(ctx, spaceID, envAlias, nil) require.NoError(t, err) @@ -234,15 +243,16 @@ func TestCollections_Cache(t *testing.T) { v4, err := svc.Get(ctx, spaceID, envAlias, colID) require.NoError(t, err) - assert.NotSame(t, v3, v4, "Ожидает что элемент после обновления был удален из кэша и будет запрошен заново из сервиса.") + assert.NotEqual(t, v3, v4, "Ожидает что элемент после обновления был удален из кэша и будет запрошен заново из сервиса.") v5, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) - assert.Same(t, v4, v5, "Ожидается получение объекта из кеша по Alias окружения.") + assert.Equal(t, v4, v5, "Ожидается получение объекта из кеша по Alias окружения.") + assert.NotSame(t, v4, v5) vl4, err := svc.List(ctx, spaceID, envAlias, nil) require.NoError(t, err) - assert.NotSame(t, vl1[0], vl4[0], "Ожидает что после обновления элементы будут запрошены заново из сервиса.") + assert.NotEqual(t, vl1[0], vl4[0], "Ожидает что после обновления элементы будут запрошены заново из сервиса.") env.AssertExpectations(t) col.AssertExpectations(t) @@ -264,11 +274,13 @@ func TestCollections_Cache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кеша по ID окружения.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кеша по ID окружения.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envAlias, colID) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кеша по Alias окружения.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кеша по Alias окружения.") + assert.NotSame(t, v2, v3) vl1, err := svc.List(ctx, spaceID, envID, nil) require.NoError(t, err) @@ -276,7 +288,7 @@ func TestCollections_Cache(t *testing.T) { vl2, err := svc.List(ctx, spaceID, envID, nil) require.NoError(t, err) assert.Len(t, vl2, 1) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кеша по ID окружения.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кеша по ID окружения.") vl3, err := svc.List(ctx, spaceID, envAlias, nil) require.NoError(t, err) @@ -295,15 +307,16 @@ func TestCollections_Cache(t *testing.T) { v4, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) - assert.NotSame(t, v3, v4, "Ожидает что элемент после обновления схемы был удален из кэша и будет запрошен заново из сервиса.") + assert.NotEqual(t, v3, v4, "Ожидает что элемент после обновления схемы был удален из кэша и будет запрошен заново из сервиса.") v5, err := svc.Get(ctx, spaceID, envAlias, colID) require.NoError(t, err) - assert.Same(t, v4, v5, "Ожидается получение объекта из кеша по Alias окружения.") + assert.Equal(t, v4, v5, "Ожидается получение объекта из кеша по Alias окружения.") + assert.NotSame(t, v4, v5) vl4, err := svc.List(ctx, spaceID, envID, nil) require.NoError(t, err) - assert.NotSame(t, vl4[0], vl3[0], "Ожидает что после обновления схемы элементы будут запрошены заново из сервиса.") + assert.NotEqual(t, vl4[0], vl3[0], "Ожидает что после обновления схемы элементы будут запрошены заново из сервиса.") vl5, err := svc.List(ctx, spaceID, envAlias, nil) require.NoError(t, err) @@ -329,11 +342,13 @@ func TestCollections_Cache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кеша по ID окружения.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кеша по ID окружения.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envAlias, colID) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кеша по Alias окружения.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кеша по Alias окружения.") + assert.NotSame(t, v2, v3) vl1, err := svc.List(ctx, spaceID, envID, nil) require.NoError(t, err) @@ -341,7 +356,7 @@ func TestCollections_Cache(t *testing.T) { vl2, err := svc.List(ctx, spaceID, envID, nil) require.NoError(t, err) assert.Len(t, vl2, 1) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кеша по ID окружения.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кеша по ID окружения.") vl3, err := svc.List(ctx, spaceID, envAlias, nil) require.NoError(t, err) @@ -391,7 +406,7 @@ func TestCollections_Cache(t *testing.T) { vl2, err := svc.List(ctx, spaceID, envID, nil) require.NoError(t, err) assert.Len(t, vl2, 1) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кеша по ID окружения.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кеша по ID окружения.") vl3, err := svc.List(ctx, spaceID, envAlias, nil) require.NoError(t, err) @@ -440,7 +455,8 @@ func TestCollections_Cache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кеша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кеша.") + assert.NotSame(t, v1, v2) time.Sleep(2 * ttl) @@ -449,6 +465,8 @@ func TestCollections_Cache(t *testing.T) { v3, err := svc.Get(ctx, spaceID, envID, colID) require.NoError(t, err) assert.NotSame(t, v3, v2, "Ожидает что элемент был удален из кэша и будет запрошен заново из сервиса.") + assert.Equal(t, v3, v2) + assert.NotSame(t, v3, v2) env.AssertExpectations(t) col.AssertExpectations(t) diff --git a/pkg/data/list.go b/pkg/data/list.go index e15a20cadcc2a22bc9c4797b8fa16413a511b5ab..90042506c4e0ff0d246239cb78cf6213d3ab934b 100644 --- a/pkg/data/list.go +++ b/pkg/data/list.go @@ -184,3 +184,11 @@ func mergeMaps(a, b map[string]interface{}) map[string]interface{} { } return out } + +func CloneSlice[T interface{ Clone() T }](s []T) []T { + result := make([]T, 0, len(s)) + for _, t := range s { + result = append(result, t.Clone()) + } + return result +} diff --git a/pkg/environments/environment.go b/pkg/environments/environment.go index e9d2b96e8337ac2ad94315b671aeea42e54c47cb..465a409129330506b5a7a9c9ebca9a14e5f10bee 100644 --- a/pkg/environments/environment.go +++ b/pkg/environments/environment.go @@ -91,4 +91,4 @@ func (e Environment) Clone() *Environment { } return clone -} \ No newline at end of file +} diff --git a/pkg/environments/middleware/caching_middleware.go b/pkg/environments/middleware/caching_middleware.go index 7e4f46d23b49daac67d57cc33f7f81b1e836c16e..c53f45e8bdcdb61f59f1af0acf11bc0f412c2629 100644 --- a/pkg/environments/middleware/caching_middleware.go +++ b/pkg/environments/middleware/caching_middleware.go @@ -5,6 +5,7 @@ import ( "strings" "git.perx.ru/perxis/perxis-go/pkg/cache" + "git.perx.ru/perxis/perxis-go/pkg/data" service "git.perx.ru/perxis/perxis-go/pkg/environments" ) @@ -39,7 +40,7 @@ func (m cachingMiddleware) Get(ctx context.Context, spaceId string, envId string value, e := m.cache.Get(makeKey(spaceId, envId)) if e == nil { - return value.(*service.Environment), err + return value.(*service.Environment).Clone(), nil } environment, err = m.next.Get(ctx, spaceId, envId) if err == nil { @@ -47,21 +48,23 @@ func (m cachingMiddleware) Get(ctx context.Context, spaceId string, envId string for _, a := range environment.Aliases { _ = m.cache.Set(makeKey(spaceId, a), environment) } + return environment.Clone(), nil } - return environment, err + return nil, err } func (m cachingMiddleware) List(ctx context.Context, spaceId string) (environments []*service.Environment, err error) { value, e := m.cache.Get(spaceId) if e == nil { - return value.([]*service.Environment), err + return data.CloneSlice(value.([]*service.Environment)), nil } environments, err = m.next.List(ctx, spaceId) if err == nil { _ = m.cache.Set(spaceId, environments) + return data.CloneSlice(environments), nil } - return environments, err + return nil, err } func (m cachingMiddleware) Update(ctx context.Context, env *service.Environment) (err error) { diff --git a/pkg/environments/middleware/caching_middleware_test.go b/pkg/environments/middleware/caching_middleware_test.go index 784ce35632e2bcd74993ce499f4ec1db329041d7..cbac396352657115e96d98b6715aa7e371a353a8 100644 --- a/pkg/environments/middleware/caching_middleware_test.go +++ b/pkg/environments/middleware/caching_middleware_test.go @@ -40,11 +40,13 @@ func TestEnvironmentsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша при повторном запросе по ID.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша при повторном запросе по ID.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envAlias) require.NoError(t, err) - assert.Same(t, v3, v2, "Ожидается получение объекта из кеша, при запросе того же объекта по alias окружения.") + assert.Equal(t, v3, v2, "Ожидается получение объекта из кеша, при запросе того же объекта по alias окружения.") + assert.NotSame(t, v3, v2) envs.AssertExpectations(t) }) @@ -61,11 +63,13 @@ func TestEnvironmentsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envAlias) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша по alias.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша по alias.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) - assert.Same(t, v3, v2, "Ожидается получение объекта из кеша, при запросе того же объекта по ID окружения.") + assert.Equal(t, v3, v2, "Ожидается получение объекта из кеша, при запросе того же объекта по ID окружения.") + assert.NotSame(t, v3, v2) envs.AssertExpectations(t) }) @@ -82,7 +86,8 @@ func TestEnvironmentsCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) envs.AssertExpectations(t) }) @@ -102,14 +107,16 @@ func TestEnvironmentsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) vl1, err := svc.List(ctx, spaceID) require.NoError(t, err) vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) err = svc.SetAlias(ctx, spaceID, envID, envAlias) require.NoError(t, err) @@ -123,11 +130,12 @@ func TestEnvironmentsCache(t *testing.T) { v5, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) - assert.Same(t, v4, v5, "Ожидается получение объекта из кэша по ID.") + assert.Equal(t, v4, v5, "Ожидается получение объекта из кэша по ID.") + assert.NotSame(t, v4, v5) vl3, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидает что объекты будут удалены из кэша и запрошены из сервиса.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидает что объекты будут удалены из кэша и запрошены из сервиса.") envs.AssertExpectations(t) }) @@ -146,18 +154,21 @@ func TestEnvironmentsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша по ID.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша по ID.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envAlias) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кэша по Alias.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кэша по Alias.") + assert.NotSame(t, v2, v3) vl1, err := svc.List(ctx, spaceID) require.NoError(t, err) vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) err = svc.RemoveAlias(ctx, spaceID, envID, envAlias) require.NoError(t, err) @@ -172,11 +183,11 @@ func TestEnvironmentsCache(t *testing.T) { v4, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) - assert.NotSame(t, v3, v4, "Ожидает что элемент был удален из кеша и получен из сервиса по ID.") + assert.NotEqual(t, v3, v4, "Ожидает что элемент был удален из кеша и получен из сервиса по ID.") vl3, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидает что объекты будут удалены из кэша и запрошены из сервиса.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидает что объекты будут удалены из кэша и запрошены из сервиса.") envs.AssertExpectations(t) }) @@ -195,18 +206,21 @@ func TestEnvironmentsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envAlias) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кэша по Alias.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кэша по Alias.") + assert.NotSame(t, v2, v3) vl1, err := svc.List(ctx, spaceID) require.NoError(t, err) vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) err = svc.Update(ctx, &environments.Environment{ID: envID, SpaceID: spaceID, Description: "EnvironmentUPD", Aliases: []string{envAlias}}) require.NoError(t, err) @@ -219,15 +233,16 @@ func TestEnvironmentsCache(t *testing.T) { v4, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) - assert.NotSame(t, v2, v4, "Ожидает что элемент был удален из кэша и будет запрошен заново из сервиса.") + assert.NotEqual(t, v2, v4, "Ожидает что элемент был удален из кэша и будет запрошен заново из сервиса.") v5, err := svc.Get(ctx, spaceID, envAlias) require.NoError(t, err) - assert.Same(t, v4, v5, "Ожидается получение объекта из кэша по Alias после обновления объекта и получения по ID.") + assert.Equal(t, v4, v5, "Ожидается получение объекта из кэша по Alias после обновления объекта и получения по ID.") + assert.NotSame(t, v4, v5) vl3, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидает что объекты будут удалены из кэша и запрошены из сервиса.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидает что объекты будут удалены из кэша и запрошены из сервиса.") envs.AssertExpectations(t) }) @@ -245,7 +260,8 @@ func TestEnvironmentsCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) err = svc.Update(ctx, &environments.Environment{ID: envID, SpaceID: spaceID, Description: "EnvironmentUPD", Aliases: []string{envAlias}}) require.NoError(t, err) @@ -254,7 +270,7 @@ func TestEnvironmentsCache(t *testing.T) { vl3, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидает что объекты будут удалены из кэша и запрошены из сервиса.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидает что объекты будут удалены из кэша и запрошены из сервиса.") envs.AssertExpectations(t) }) @@ -273,18 +289,21 @@ func TestEnvironmentsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, spaceID, envAlias) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кэша по Alias.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кэша по Alias.") + assert.NotSame(t, v2, v3) vl1, err := svc.List(ctx, spaceID) require.NoError(t, err) vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) err = svc.Delete(ctx, spaceID, envID) require.NoError(t, err) @@ -320,7 +339,8 @@ func TestEnvironmentsCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) envs.On("Create", mock.Anything, mock.Anything).Return(&environments.Environment{ID: "envID2", SpaceID: spaceID, Description: "Environment2"}, nil).Once() _, err = svc.Create(ctx, &environments.Environment{ID: "envID2", SpaceID: spaceID, Description: "Environment2"}) @@ -349,15 +369,16 @@ func TestEnvironmentsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, "envID2") require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") - + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) _, err = svc.Get(ctx, spaceID, envID) require.NoError(t, err) v5, err := svc.Get(ctx, spaceID, "envID2") require.NoError(t, err) assert.NotSame(t, v2, v5, "Ожидает что объект был удален из кэша и будет запрошен заново из сервиса.") - + assert.Equal(t, v2, v5) + assert.NotSame(t, v2, v5) envs.AssertExpectations(t) }) @@ -372,7 +393,8 @@ func TestEnvironmentsCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) time.Sleep(2 * ttl) @@ -380,6 +402,8 @@ func TestEnvironmentsCache(t *testing.T) { v3, err := svc.Get(ctx, spaceID, envID) require.NoError(t, err) assert.NotSame(t, v2, v3, "Ожидает что объект был удален из кэша и будет запрошен заново из сервиса.") + assert.Equal(t, v2, v3) + assert.NotSame(t, v2, v3) envs.AssertExpectations(t) }) diff --git a/pkg/invitations/invitation.go b/pkg/invitations/invitation.go index 5dc5913774fc5774076823309abdf52b195c87c2..a5b91ed006693748deb71877b8e555e485b0c6c8 100644 --- a/pkg/invitations/invitation.go +++ b/pkg/invitations/invitation.go @@ -14,3 +14,16 @@ type Invitation struct { CreatedAt *time.Time `bson:"createdAt"` ValidUntil *time.Time `bson:"validUntil"` } + +func (i Invitation) Clone() *Invitation { + return &Invitation{ + ID: i.ID, + Email: i.Email, + OrgID: i.OrgID, + SpaceID: i.SpaceID, + OwnerID: i.OwnerID, + Role: i.Role, + CreatedAt: i.CreatedAt, + ValidUntil: i.ValidUntil, + } +} diff --git a/pkg/invitations/middleware/caching_middleware.go b/pkg/invitations/middleware/caching_middleware.go index 698ee51195e4a958b42a0bd44dadfa125a2c0be8..b14a155dc04022baed930f4252ec63caf47dab3b 100644 --- a/pkg/invitations/middleware/caching_middleware.go +++ b/pkg/invitations/middleware/caching_middleware.go @@ -30,13 +30,14 @@ func (m cachingMiddleware) Get(ctx context.Context, invitationId string) (inv *s value, e := m.cache.Get(invitationId) if e == nil { - return value.(*service.Invitation), err + return value.(*service.Invitation).Clone(), nil } inv, err = m.next.Get(ctx, invitationId) if err == nil { _ = m.cache.Set(invitationId, inv) + return inv.Clone(), nil } - return inv, err + return nil, err } func (m cachingMiddleware) Accept(ctx context.Context, invitationId string, userId string) (err error) { diff --git a/pkg/invitations/middleware/caching_middleware_test.go b/pkg/invitations/middleware/caching_middleware_test.go index e7fac6f545463644ddd7476a43123f248b9a16b8..46d0a44342822a877be1feffbc396e37606e8157 100644 --- a/pkg/invitations/middleware/caching_middleware_test.go +++ b/pkg/invitations/middleware/caching_middleware_test.go @@ -41,7 +41,8 @@ func TestLocalesCache(t *testing.T) { v2, err := svc.Get(ctx, invID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается что при повторном запросе объект будет получен из кэша.") + assert.Equal(t, v1, v2, "Ожидается что при повторном запросе объект будет получен из кэша.") + assert.NotSame(t, v1, v2) inv.AssertExpectations(t) }) @@ -59,7 +60,8 @@ func TestLocalesCache(t *testing.T) { v2, err := svc.Get(ctx, invID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается что при повторном запросе объект будет получен из кэша.") + assert.Equal(t, v1, v2, "Ожидается что при повторном запросе объект будет получен из кэша.") + assert.NotSame(t, v1, v2) inv.On("Accept", mock.Anything, invID, usrID).Return(nil).Once() inv.On("Get", mock.Anything, invID).Return(nil, errNotFound).Once() @@ -86,7 +88,8 @@ func TestLocalesCache(t *testing.T) { v2, err := svc.Get(ctx, invID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается что при повторном запросе объект будет получен из кэша.") + assert.Equal(t, v1, v2, "Ожидается что при повторном запросе объект будет получен из кэша.") + assert.NotSame(t, v1, v2) inv.On("Delete", mock.Anything, invID).Return(nil).Once() inv.On("Get", mock.Anything, invID).Return(nil, errNotFound).Once() @@ -113,7 +116,8 @@ func TestLocalesCache(t *testing.T) { v2, err := svc.Get(ctx, invID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается что при повторном запросе объект будет получен из кэша.") + assert.Equal(t, v1, v2, "Ожидается что при повторном запросе объект будет получен из кэша.") + assert.NotSame(t, v1, v2) time.Sleep(2 * ttl) @@ -122,6 +126,8 @@ func TestLocalesCache(t *testing.T) { v3, err := svc.Get(ctx, invID) require.NoError(t, err) assert.NotSame(t, v2, v3, "Ожидается что при истечении ttl кеш будет очищен..") + assert.Equal(t, v2, v3) + assert.NotSame(t, v2, v3) inv.AssertExpectations(t) }) diff --git a/pkg/locales/locale.go b/pkg/locales/locale.go index f45f1d85ca9688e4b89e47d58f92412245d02f65..520bc68c68c5f1bbe14398237c5a732ed192b212 100644 --- a/pkg/locales/locale.go +++ b/pkg/locales/locale.go @@ -23,6 +23,21 @@ type Locale struct { Disabled bool `json:"disabled" bson:"disabled"` // Запретить использование локали. Нельзя создавать и редактировать контент для данной локали (кроме default) } +func (l Locale) Clone() *Locale { + return &Locale{ + ID: l.ID, + SpaceID: l.SpaceID, + Name: l.Name, + NativeName: l.NativeName, + Code: l.Code, + Fallback: l.Fallback, + Direction: l.Direction, + Weight: l.Weight, + NoPublish: l.NoPublish, + Disabled: l.Disabled, + } +} + func (locale *Locale) IsDefault() bool { return locale.ID == DefaultID } diff --git a/pkg/locales/middleware/caching_middleware.go b/pkg/locales/middleware/caching_middleware.go index 8a79a152981f95d6c61cc6177ea1900d4900c9a2..64f82bc2347323140674cb7375bfe41a36a5bfb0 100644 --- a/pkg/locales/middleware/caching_middleware.go +++ b/pkg/locales/middleware/caching_middleware.go @@ -4,6 +4,7 @@ import ( "context" "git.perx.ru/perxis/perxis-go/pkg/cache" + "git.perx.ru/perxis/perxis-go/pkg/data" service "git.perx.ru/perxis/perxis-go/pkg/locales" ) @@ -43,13 +44,14 @@ func (m cachingMiddleware) List(ctx context.Context, spaceId string) (locales [] value, e := m.cache.Get(spaceId) if e == nil { - return value.([]*service.Locale), err + return data.CloneSlice(value.([]*service.Locale)), nil } locales, err = m.next.List(ctx, spaceId) if err == nil { _ = m.cache.Set(spaceId, locales) + return data.CloneSlice(locales), nil } - return locales, err + return nil, err } func (m cachingMiddleware) Delete(ctx context.Context, spaceId string, localeId string) (err error) { diff --git a/pkg/locales/middleware/caching_middleware_test.go b/pkg/locales/middleware/caching_middleware_test.go index c738c98756adeb172fc2e648eea714d826b9ba73..25b542c840c228324f843267ae3968f96d0ddfe5 100644 --- a/pkg/locales/middleware/caching_middleware_test.go +++ b/pkg/locales/middleware/caching_middleware_test.go @@ -37,7 +37,8 @@ func TestLocalesCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается что при повторном запросе объекты будут получены из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается что при повторном запросе объекты будут получены из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) loc.AssertExpectations(t) }) @@ -55,7 +56,8 @@ func TestLocalesCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается что при повторном запросе объекты будут получены из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается что при повторном запросе объекты будут получены из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) loc.On("Delete", mock.Anything, spaceID, loc1).Return(nil).Once() @@ -83,7 +85,8 @@ func TestLocalesCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается что при повторном запросе объекты будут получены из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается что при повторном запросе объекты будут получены из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) loc.On("Create", mock.Anything, mock.Anything).Return(&locales.Locale{ID: loc2, Name: "name2", SpaceID: spaceID}, nil).Once() @@ -115,7 +118,8 @@ func TestLocalesCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается что при повторном запросе объекты будут получены из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается что при повторном запросе объекты будут получены из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) loc.On("Update", mock.Anything, mock.Anything).Return(nil).Once() @@ -147,7 +151,8 @@ func TestLocalesCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается что при повторном запросе объекты будут получены из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается что при повторном запросе объекты будут получены из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) time.Sleep(2 * ttl) loc.On("List", mock.Anything, spaceID).Return([]*locales.Locale{{ID: loc1, Name: "name1", SpaceID: spaceID}}, nil).Once() @@ -155,6 +160,8 @@ func TestLocalesCache(t *testing.T) { vl3, err := svc.List(ctx, spaceID) require.NoError(t, err) assert.NotSame(t, vl2[0], vl3[0], "Ожидается что элементы будут получены из кэша.") + assert.Equal(t, vl2[0], vl3[0]) + assert.NotSame(t, vl2[0], vl3[0]) loc.AssertExpectations(t) }) diff --git a/pkg/members/members.go b/pkg/members/members.go index 3013b1ff2d4399bf627927cd1e80b9076b8b05b3..28ae060e2dacf12a61ef3e9d99831e01689d39b2 100644 --- a/pkg/members/members.go +++ b/pkg/members/members.go @@ -11,6 +11,14 @@ type Member struct { Role Role `bson:"role"` } +func (m Member) Clone() *Member { + return &Member{ + OrgId: m.OrgId, + UserId: m.UserId, + Role: m.Role, + } +} + type Role uint const ( diff --git a/pkg/members/middleware/caching_middleware.go b/pkg/members/middleware/caching_middleware.go index 00ddb61aa22b837798b6f7f46fd24525e6119adc..4c61bff9078028009130bc7378908a6db551bba2 100644 --- a/pkg/members/middleware/caching_middleware.go +++ b/pkg/members/middleware/caching_middleware.go @@ -5,6 +5,7 @@ import ( "strings" "git.perx.ru/perxis/perxis-go/pkg/cache" + "git.perx.ru/perxis/perxis-go/pkg/data" service "git.perx.ru/perxis/perxis-go/pkg/members" ) @@ -79,24 +80,26 @@ func (m cachingMiddleware) ListMembers(ctx context.Context, orgId string) (membe value, e := m.cache.Get(makeKey(orgId)) if e == nil { - return value.([]*service.Member), err + return data.CloneSlice(value.([]*service.Member)), nil } members, err = m.next.ListMembers(ctx, orgId) if err == nil { _ = m.cache.Set(makeKey(orgId), members) + return data.CloneSlice(members), nil } - return members, err + return nil, err } func (m cachingMiddleware) ListOrganizations(ctx context.Context, userId string) (members []*service.Member, err error) { value, e := m.cache.Get(makeKey(userId)) if e == nil { - return value.([]*service.Member), err + return data.CloneSlice(value.([]*service.Member)), nil } members, err = m.next.ListOrganizations(ctx, userId) if err == nil { _ = m.cache.Set(makeKey(userId), members) + return data.CloneSlice(members), nil } - return members, err + return nil, err } diff --git a/pkg/organizations/middleware/caching_middleware.go b/pkg/organizations/middleware/caching_middleware.go index ecee27276835402a0381086d9032ebd22acedcf1..c6503200cfbc47915475a95c154a253dec51e29c 100644 --- a/pkg/organizations/middleware/caching_middleware.go +++ b/pkg/organizations/middleware/caching_middleware.go @@ -30,13 +30,14 @@ func (m cachingMiddleware) Get(ctx context.Context, orgId string) (organization value, e := m.cache.Get(orgId) if e == nil { - return value.(*service.Organization), err + return value.(*service.Organization).Clone(), nil } organization, err = m.next.Get(ctx, orgId) if err == nil { _ = m.cache.Set(orgId, organization) + return organization.Clone(), nil } - return organization, err + return nil, err } func (m cachingMiddleware) Update(ctx context.Context, org *service.Organization) (err error) { diff --git a/pkg/organizations/middleware/caching_middleware_test.go b/pkg/organizations/middleware/caching_middleware_test.go index 3f30262041b3dfdd24b40810656e9478cc53a688..f9999cfce509debda6b49d5aa5ee26a3d60d0f4f 100644 --- a/pkg/organizations/middleware/caching_middleware_test.go +++ b/pkg/organizations/middleware/caching_middleware_test.go @@ -37,7 +37,8 @@ func TestOrganizationsCache(t *testing.T) { v2, err := svc.Get(ctx, orgId) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) orgs.AssertExpectations(t) }) @@ -54,7 +55,8 @@ func TestOrganizationsCache(t *testing.T) { v2, err := svc.Get(ctx, orgId) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) orgs.On("Update", mock.Anything, mock.Anything).Return(nil).Once() err = svc.Update(ctx, &organizations.Organization{ID: orgId, Name: "OrganizationUPD"}) @@ -64,7 +66,7 @@ func TestOrganizationsCache(t *testing.T) { v3, err := svc.Get(ctx, orgId) require.NoError(t, err) - assert.NotSame(t, v2, v3, "Ожидается удаление объекта из кэша после обновления и получение заново из сервиса.") + assert.NotEqual(t, v2, v3, "Ожидается удаление объекта из кэша после обновления и получение заново из сервиса.") orgs.AssertExpectations(t) }) @@ -80,7 +82,8 @@ func TestOrganizationsCache(t *testing.T) { v2, err := svc.Get(ctx, orgId) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) orgs.On("Delete", mock.Anything, mock.Anything).Return(nil).Once() err = svc.Delete(ctx, orgId) @@ -105,7 +108,8 @@ func TestOrganizationsCache(t *testing.T) { v2, err := svc.Get(ctx, orgId) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) time.Sleep(2 * ttl) @@ -114,6 +118,8 @@ func TestOrganizationsCache(t *testing.T) { v3, err := svc.Get(ctx, orgId) require.NoError(t, err) assert.NotSame(t, v2, v3, "Ожидается удаление объекта из кэша и получение заново из сервиса.") + assert.Equal(t, v2, v3) + assert.NotSame(t, v2, v3) orgs.AssertExpectations(t) }) diff --git a/pkg/organizations/organization.go b/pkg/organizations/organization.go index b95daa6988710d26fcda200eebef8afeff9158df..8c6df31c766487d3978ef35e73d043343ab7d090 100644 --- a/pkg/organizations/organization.go +++ b/pkg/organizations/organization.go @@ -8,6 +8,16 @@ type Organization struct { OwnerID *string `bson:"-"` } +func (o Organization) Clone() *Organization { + return &Organization{ + ID: o.ID, + Name: o.Name, + Description: o.Description, + LogoURL: o.LogoURL, + OwnerID: o.OwnerID, + } +} + func (o *Organization) SetOwnerID(s string) *Organization { o.OwnerID = &s return o diff --git a/pkg/roles/middleware/caching_middleware.go b/pkg/roles/middleware/caching_middleware.go index 8537544fcf3809f6dbfafe3860a8b7f0c0a9de28..2bcb04d3df7278d619fe80b2a6b02c48ea58f1fb 100644 --- a/pkg/roles/middleware/caching_middleware.go +++ b/pkg/roles/middleware/caching_middleware.go @@ -5,6 +5,7 @@ import ( "strings" "git.perx.ru/perxis/perxis-go/pkg/cache" + "git.perx.ru/perxis/perxis-go/pkg/data" service "git.perx.ru/perxis/perxis-go/pkg/roles" ) @@ -38,25 +39,27 @@ func (m cachingMiddleware) Get(ctx context.Context, spaceId string, roleId strin key := makeKey(spaceId, roleId) value, e := m.cache.Get(key) if e == nil { - return value.(*service.Role), err + return value.(*service.Role).Clone(), nil } rl, err = m.next.Get(ctx, spaceId, roleId) if err == nil { _ = m.cache.Set(key, rl) + return rl.Clone(), nil } - return rl, err + return nil, err } func (m cachingMiddleware) List(ctx context.Context, spaceId string) (roles []*service.Role, err error) { value, e := m.cache.Get(spaceId) if e == nil { - return value.([]*service.Role), err + return data.CloneSlice(value.([]*service.Role)), nil } roles, err = m.next.List(ctx, spaceId) if err == nil { _ = m.cache.Set(spaceId, roles) + return data.CloneSlice(roles), nil } - return roles, err + return nil, err } func (m cachingMiddleware) Update(ctx context.Context, role *service.Role) (err error) { diff --git a/pkg/roles/middleware/caching_middleware_test.go b/pkg/roles/middleware/caching_middleware_test.go index 9d5d64f4231cf8bd86d533224fd50e762eebdcab..b9ac8ec826439319348bac2b13fc743c3753d024 100644 --- a/pkg/roles/middleware/caching_middleware_test.go +++ b/pkg/roles/middleware/caching_middleware_test.go @@ -39,7 +39,8 @@ func TestRolesCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, roleID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.NotSame(t, v1, v2) rl.AssertExpectations(t) }) @@ -56,7 +57,8 @@ func TestRolesCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) rl.AssertExpectations(t) }) @@ -75,14 +77,16 @@ func TestRolesCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, roleID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объектов из кэша.") + assert.Equal(t, v1, v2, "Ожидается при повторном запросе получение объектов из кэша.") + assert.NotSame(t, v1, v2) vl1, err := svc.List(ctx, spaceID) require.NoError(t, err) vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) rl.On("Update", mock.Anything, mock.Anything).Return(nil).Once() @@ -94,11 +98,11 @@ func TestRolesCache(t *testing.T) { v3, err := svc.Get(ctx, spaceID, roleID) require.NoError(t, err) - assert.NotSame(t, v2, v3, "Ожидается что кеш объекта был удален после его обновления и объект был запрошен из сервиса.") + assert.NotEqual(t, v2, v3, "Ожидается что кеш объекта был удален после его обновления и объект был запрошен из сервиса.") vl3, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидается что кеш объектов был удален после обновления объекта.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидается что кеш объектов был удален после обновления объекта.") rl.AssertExpectations(t) }) @@ -116,14 +120,16 @@ func TestRolesCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, roleID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.NotSame(t, v1, v2) vl1, err := svc.List(ctx, spaceID) require.NoError(t, err) vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) rl.On("Update", mock.Anything, mock.Anything).Return(nil).Once() @@ -158,7 +164,8 @@ func TestRolesCache(t *testing.T) { vl2, err := svc.List(ctx, spaceID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объекта из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объекта из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) rl.On("Create", mock.Anything, mock.Anything).Return(&roles.Role{ID: "roleID2", SpaceID: spaceID, Description: "Role2"}, nil).Once() @@ -186,7 +193,8 @@ func TestRolesCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID, roleID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) time.Sleep(2 * ttl) rl.On("Get", mock.Anything, spaceID, roleID).Return(&roles.Role{ID: roleID, SpaceID: spaceID, Description: "Role"}, nil).Once() @@ -194,6 +202,8 @@ func TestRolesCache(t *testing.T) { v3, err := svc.Get(ctx, spaceID, roleID) require.NoError(t, err) assert.NotSame(t, v2, v3, "Ожидается что объект был удален из кеша и получен заново из сервиса.") + assert.Equal(t, v2, v3) + assert.NotSame(t, v2, v3) rl.AssertExpectations(t) }) diff --git a/pkg/roles/role.go b/pkg/roles/role.go index 370470675cd40ae417d38b2ae8b8f7c4e7a63cfe..579a9664ca87382c7c7533ecf502df3d6cb5c990 100644 --- a/pkg/roles/role.go +++ b/pkg/roles/role.go @@ -2,6 +2,7 @@ package roles import ( "context" + "slices" "git.perx.ru/perxis/perxis-go/pkg/data" "git.perx.ru/perxis/perxis-go/pkg/environments" @@ -34,6 +35,17 @@ type Role struct { AllowManagement bool `json:"allow_management" bson:"allow_management"` } +func (r Role) Clone() *Role { + return &Role{ + ID: r.ID, + SpaceID: r.SpaceID, + Description: r.Description, + Environments: slices.Clone(r.Environments), + Rules: data.CloneSlice(r.Rules), + AllowManagement: r.AllowManagement, + } +} + func (r Role) CanAccessEnvironment(ctx context.Context, env *environments.Environment, service environments.Environments) bool { if env.SpaceID == "" || env.ID == "" { return false diff --git a/pkg/spaces/middleware/caching_middleware.go b/pkg/spaces/middleware/caching_middleware.go index 46c9ef468b39f15f0d462de695f1da4f38213832..c7f35de12106e9aa828e56ebd6f6ec4361c70da7 100644 --- a/pkg/spaces/middleware/caching_middleware.go +++ b/pkg/spaces/middleware/caching_middleware.go @@ -4,6 +4,7 @@ import ( "context" "git.perx.ru/perxis/perxis-go/pkg/cache" + "git.perx.ru/perxis/perxis-go/pkg/data" "git.perx.ru/perxis/perxis-go/pkg/options" service "git.perx.ru/perxis/perxis-go/pkg/spaces" ) @@ -39,20 +40,21 @@ func (m cachingMiddleware) Get(ctx context.Context, spaceId string) (sp *service value, e := m.cache.Get(spaceId) if e == nil { - return value.(*service.Space), err + return value.(*service.Space).Clone(), nil } sp, err = m.next.Get(ctx, spaceId) if err == nil { _ = m.cache.Set(spaceId, sp) + return sp.Clone(), nil } - return sp, err + return nil, err } func (m cachingMiddleware) List(ctx context.Context, orgId string) (spaces []*service.Space, err error) { value, e := m.cache.Get(orgKey(orgId)) if e == nil { - return value.([]*service.Space), err + return data.CloneSlice(value.([]*service.Space)), nil } spaces, err = m.next.List(ctx, orgId) if err == nil { @@ -60,8 +62,9 @@ func (m cachingMiddleware) List(ctx context.Context, orgId string) (spaces []*se for _, s := range spaces { _ = m.cache.Set(s.ID, s) } + return data.CloneSlice(spaces), nil } - return spaces, err + return nil, err } func (m cachingMiddleware) Find(ctx context.Context, filter *service.Filter, fo *options.FindOptions) (spaces []*service.Space, total int, err error) { diff --git a/pkg/spaces/middleware/caching_middleware_test.go b/pkg/spaces/middleware/caching_middleware_test.go index e87ceb38c79c6b15d76ab6f6ff8f628a680a5aa6..0674c932eb4e5f9d519a587a45cc4c5003b8f7d7 100644 --- a/pkg/spaces/middleware/caching_middleware_test.go +++ b/pkg/spaces/middleware/caching_middleware_test.go @@ -40,7 +40,8 @@ func TestRolesCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.NotSame(t, v1, v2) sp.AssertExpectations(t) }) @@ -57,7 +58,8 @@ func TestRolesCache(t *testing.T) { vl2, err := svc.List(ctx, orgID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) sp.AssertExpectations(t) }) @@ -76,14 +78,16 @@ func TestRolesCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.NotSame(t, v1, v2) vl1, err := svc.List(ctx, orgID) require.NoError(t, err) vl2, err := svc.List(ctx, orgID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) sp.On("Update", mock.Anything, mock.Anything).Return(nil).Once() @@ -95,11 +99,11 @@ func TestRolesCache(t *testing.T) { v3, err := svc.Get(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, v2, v3, "Ожидается что кеш объекта был удален после обновления объекта.") + assert.NotEqual(t, v2, v3, "Ожидается что кеш объекта был удален после обновления объекта.") vl3, err := svc.List(ctx, orgID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидается что кеш объектов был удален после обновления объекта.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидается что кеш объектов был удален после обновления объекта.") sp.AssertExpectations(t) }) @@ -117,14 +121,16 @@ func TestRolesCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.NotSame(t, v1, v2) vl1, err := svc.List(ctx, orgID) require.NoError(t, err) vl2, err := svc.List(ctx, orgID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) sp.On("UpdateConfig", mock.Anything, spaceID, mock.Anything).Return(nil).Once() @@ -136,11 +142,11 @@ func TestRolesCache(t *testing.T) { v3, err := svc.Get(ctx, spaceID) require.NoError(t, err) - assert.NotSame(t, v2, v3, "Ожидается что кеш объекта был удален после обновления объекта.") + assert.NotEqual(t, v2, v3, "Ожидается что кеш объекта был удален после обновления объекта.") vl3, err := svc.List(ctx, orgID) require.NoError(t, err) - assert.NotSame(t, vl2[0], vl3[0], "Ожидается что кеш объектов был удален после обновления объекта.") + assert.NotEqual(t, vl2[0], vl3[0], "Ожидается что кеш объектов был удален после обновления объекта.") sp.AssertExpectations(t) }) @@ -158,14 +164,16 @@ func TestRolesCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.NotSame(t, v1, v2) vl1, err := svc.List(ctx, orgID) require.NoError(t, err) vl2, err := svc.List(ctx, orgID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) sp.On("Delete", mock.Anything, spaceID).Return(nil).Once() @@ -198,7 +206,8 @@ func TestRolesCache(t *testing.T) { vl2, err := svc.List(ctx, orgID) require.NoError(t, err) - assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.Equal(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.") + assert.NotSame(t, vl1[0], vl2[0]) sp.On("Create", mock.Anything, mock.Anything).Return(&spaces.Space{ID: "spaceID2", OrgID: orgID, Name: "Space2"}, nil).Once() @@ -210,6 +219,8 @@ func TestRolesCache(t *testing.T) { vl3, err := svc.List(ctx, orgID) require.NoError(t, err) assert.NotSame(t, vl2[0], vl3[0], "Ожидается что кеш объектов был удален после создания нового объекта.") + assert.Equal(t, vl2[0], vl3[0]) + assert.NotSame(t, vl2[0], vl3[0]) sp.AssertExpectations(t) }) @@ -226,7 +237,8 @@ func TestRolesCache(t *testing.T) { v2, err := svc.Get(ctx, spaceID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.") + assert.NotSame(t, v1, v2) time.Sleep(2 * ttl) sp.On("Get", mock.Anything, spaceID).Return(&spaces.Space{ID: spaceID, OrgID: orgID, Name: "Space"}, nil).Once() @@ -234,6 +246,8 @@ func TestRolesCache(t *testing.T) { v3, err := svc.Get(ctx, spaceID) require.NoError(t, err) assert.NotSame(t, v2, v3, "Ожидается удаление объекта из кэша по истечению ttl.") + assert.Equal(t, v2, v3) + assert.NotSame(t, v2, v3) sp.AssertExpectations(t) }) diff --git a/pkg/users/middleware/caching_middleware.go b/pkg/users/middleware/caching_middleware.go index ee0bf4a0599276737b9f258e7f30995388edc8f3..825da6a28caabeee0f71d9030b60c8152e884570 100644 --- a/pkg/users/middleware/caching_middleware.go +++ b/pkg/users/middleware/caching_middleware.go @@ -30,7 +30,7 @@ func (m cachingMiddleware) Get(ctx context.Context, userId string) (user *servic value, e := m.cache.Get(userId) if e == nil { - return value.(*service.User), err + return value.(*service.User).Clone(), nil } user, err = m.next.Get(ctx, userId) if err == nil { @@ -38,8 +38,9 @@ func (m cachingMiddleware) Get(ctx context.Context, userId string) (user *servic for _, i := range user.Identities { _ = m.cache.Set(i, user) } + return user.Clone(), nil } - return user, err + return nil, err } func (m cachingMiddleware) Find(ctx context.Context, filter *service.Filter, options *services.FindOptions) (users []*service.User, total int, err error) { @@ -78,7 +79,7 @@ func (m cachingMiddleware) GetByIdentity(ctx context.Context, identity string) ( value, e := m.cache.Get(identity) if e == nil { - return value.(*service.User), err + return value.(*service.User).Clone(), nil } user, err = m.next.GetByIdentity(ctx, identity) if err == nil { @@ -86,6 +87,7 @@ func (m cachingMiddleware) GetByIdentity(ctx context.Context, identity string) ( for _, i := range user.Identities { _ = m.cache.Set(i, user) } + return user.Clone(), nil } - return user, err + return nil, err } diff --git a/pkg/users/middleware/caching_middleware_test.go b/pkg/users/middleware/caching_middleware_test.go index edc9176baac6656a1d70995b0881055b83642293..c5755407c6ffbc163f86ed548ad4b50c5d8bfc94 100644 --- a/pkg/users/middleware/caching_middleware_test.go +++ b/pkg/users/middleware/caching_middleware_test.go @@ -38,11 +38,13 @@ func TestUsersCache(t *testing.T) { v2, err := svc.Get(ctx, userID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) v3, err := svc.GetByIdentity(ctx, identity) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кэша при запросе по Identity.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кэша при запросе по Identity.") + assert.NotSame(t, v2, v3) usrs.AssertExpectations(t) }) @@ -60,11 +62,13 @@ func TestUsersCache(t *testing.T) { v2, err := svc.GetByIdentity(ctx, identity) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) v3, err := svc.Get(ctx, userID) require.NoError(t, err) - assert.Same(t, v2, v3, "Ожидается получение объекта из кэша при запросе по userID.") + assert.Equal(t, v2, v3, "Ожидается получение объекта из кэша при запросе по userID.") + assert.NotSame(t, v2, v3) usrs.AssertExpectations(t) }) @@ -84,7 +88,8 @@ func TestUsersCache(t *testing.T) { v2, err := svc.GetByIdentity(ctx, identity) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) err = svc.Update(ctx, &users.User{ID: userID, Name: "New User", Identities: []string{identity}}) require.NoError(t, err) @@ -93,12 +98,13 @@ func TestUsersCache(t *testing.T) { v3, err := svc.GetByIdentity(ctx, identity) require.NoError(t, err) - assert.NotSame(t, v3, v2, "Ожидается удаление объекта из кеша после обновления и получение его заново из сервиса.") + assert.NotEqual(t, v3, v2, "Ожидается удаление объекта из кеша после обновления и получение его заново из сервиса.") v4, err := svc.Get(ctx, userID) require.NoError(t, err) - assert.NotSame(t, v4, v2) - assert.Same(t, v4, v3, "Ожидается получение нового обьекта из кеша.") + assert.NotEqual(t, v4, v2) + assert.Equal(t, v4, v3, "Ожидается получение нового обьекта из кеша.") + assert.NotSame(t, v4, v3) usrs.AssertExpectations(t) }) @@ -117,7 +123,8 @@ func TestUsersCache(t *testing.T) { v2, err := svc.GetByIdentity(ctx, identity) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) err = svc.Delete(ctx, userID) require.NoError(t, err) @@ -149,7 +156,8 @@ func TestUsersCache(t *testing.T) { v2, err := svc.Get(ctx, userID) require.NoError(t, err) - assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.Equal(t, v1, v2, "Ожидается получение объекта из кэша.") + assert.NotSame(t, v1, v2) time.Sleep(2 * ttl) @@ -158,6 +166,8 @@ func TestUsersCache(t *testing.T) { v3, err := svc.Get(ctx, userID) require.NoError(t, err) assert.NotSame(t, v2, v3, "Ожидается получение объекта из кэша при запросе по Identity.") + assert.Equal(t, v2, v3) + assert.NotSame(t, v2, v3) usrs.AssertExpectations(t) })