package middleware import ( "context" "strings" "git.perx.ru/perxis/perxis-go/pkg/cache" envService "git.perx.ru/perxis/perxis-go/pkg/environments" service "git.perx.ru/perxis/perxis-go/pkg/items" ) func makeKey(ss ...string) string { return strings.Join(ss, "-") } func CachingMiddleware(cache, cachePublished cache.Cache, envs envService.Environments) Middleware { return func(next service.Items) service.Items { return &cachingMiddleware{ cache: cache, cachePublished: cachePublished, Items: next, envs: envs, } } } type cachingMiddleware struct { cache cache.Cache cachePublished cache.Cache envs envService.Environments service.Items } func (m cachingMiddleware) Get(ctx context.Context, spaceId, envId, collectionId, itemId string, options ...*service.GetOptions) (itm *service.Item, err error) { value, e := m.cache.Get(makeKey(spaceId, envId, collectionId, itemId)) if e == nil { return value.(*service.Item).Clone(), err } itm, err = m.Items.Get(ctx, spaceId, envId, collectionId, itemId, options...) if err == nil { env, err := m.envs.Get(ctx, itm.SpaceID, itm.EnvID) if err != nil { return nil, err } _ = m.cache.Set(makeKey(itm.SpaceID, env.ID, itm.CollectionID, itm.ID), itm) for _, al := range env.Aliases { _ = m.cache.Set(makeKey(itm.SpaceID, al, itm.CollectionID, itm.ID), itm) } } return itm.Clone(), err } func (m cachingMiddleware) Update(ctx context.Context, item *service.Item, options ...*service.UpdateOptions) (err error) { err = m.Items.Update(ctx, item, options...) if err == nil { env, err := m.envs.Get(ctx, item.SpaceID, item.EnvID) if err != nil { return err } _ = m.cache.Remove(makeKey(item.SpaceID, env.ID, item.CollectionID, item.ID)) _ = m.cachePublished.Remove(makeKey(item.SpaceID, env.ID, item.CollectionID, item.ID)) for _, al := range env.Aliases { _ = m.cache.Remove(makeKey(item.SpaceID, al, item.CollectionID, item.ID)) _ = m.cachePublished.Remove(makeKey(item.SpaceID, al, item.CollectionID, item.ID)) } } return err } func (m cachingMiddleware) Delete(ctx context.Context, del *service.Item, options ...*service.DeleteOptions) (err error) { err = m.Items.Delete(ctx, del, options...) if err == nil { env, err := m.envs.Get(ctx, del.SpaceID, del.EnvID) if err != nil { return err } _ = m.cache.Remove(makeKey(del.SpaceID, env.ID, del.CollectionID, del.ID)) _ = m.cachePublished.Remove(makeKey(del.SpaceID, env.ID, del.CollectionID, del.ID)) for _, al := range env.Aliases { _ = m.cache.Remove(makeKey(del.SpaceID, al, del.CollectionID, del.ID)) _ = m.cachePublished.Remove(makeKey(del.SpaceID, al, del.CollectionID, del.ID)) } } return err } func (m cachingMiddleware) Publish(ctx context.Context, item *service.Item, options ...*service.PublishOptions) (err error) { err = m.Items.Publish(ctx, item, options...) if err == nil { env, err := m.envs.Get(ctx, item.SpaceID, item.EnvID) if err != nil { return err } _ = m.cache.Remove(makeKey(item.SpaceID, env.ID, item.CollectionID, item.ID)) _ = m.cachePublished.Remove(makeKey(item.SpaceID, env.ID, item.CollectionID, item.ID)) for _, al := range env.Aliases { _ = m.cache.Remove(makeKey(item.SpaceID, al, item.CollectionID, item.ID)) _ = m.cachePublished.Remove(makeKey(item.SpaceID, al, item.CollectionID, item.ID)) } } return err } func (m cachingMiddleware) Unpublish(ctx context.Context, item *service.Item, options ...*service.UnpublishOptions) (err error) { err = m.Items.Unpublish(ctx, item, options...) if err == nil { env, err := m.envs.Get(ctx, item.SpaceID, item.EnvID) if err != nil { return err } _ = m.cache.Remove(makeKey(item.SpaceID, env.ID, item.CollectionID, item.ID)) _ = m.cachePublished.Remove(makeKey(item.SpaceID, env.ID, item.CollectionID, item.ID)) for _, al := range env.Aliases { _ = m.cache.Remove(makeKey(item.SpaceID, al, item.CollectionID, item.ID)) _ = m.cachePublished.Remove(makeKey(item.SpaceID, al, item.CollectionID, item.ID)) } } return err } func (m cachingMiddleware) GetPublished(ctx context.Context, spaceId, envId, collectionId, itemId string, options ...*service.GetPublishedOptions) (itm *service.Item, err error) { opts := service.MergeGetPublishedOptions(options...) val, e := m.cachePublished.Get(makeKey(spaceId, envId, collectionId, itemId)) if e == nil { value := val.(map[string]*service.Item) if i, ok := value[opts.LocaleID]; ok { return i.Clone(), nil } } itm, err = m.Items.GetPublished(ctx, spaceId, envId, collectionId, itemId, opts) if err == nil { env, err := m.envs.Get(ctx, itm.SpaceID, itm.EnvID) if err != nil { return nil, err } var value = make(map[string]*service.Item) if val != nil { value = val.(map[string]*service.Item) } value[opts.LocaleID] = itm _ = m.cachePublished.Set(makeKey(itm.SpaceID, env.ID, itm.CollectionID, itm.ID), value) for _, al := range env.Aliases { _ = m.cachePublished.Set(makeKey(itm.SpaceID, al, itm.CollectionID, itm.ID), value) } } return itm.Clone(), err } func (m cachingMiddleware) Archive(ctx context.Context, item *service.Item, options ...*service.ArchiveOptions) (err error) { err = m.Items.Archive(ctx, item, options...) if err == nil { env, err := m.envs.Get(ctx, item.SpaceID, item.EnvID) if err != nil { return err } _ = m.cache.Remove(makeKey(item.SpaceID, env.ID, item.CollectionID, item.ID)) _ = m.cachePublished.Remove(makeKey(item.SpaceID, env.ID, item.CollectionID, item.ID)) for _, al := range env.Aliases { _ = m.cache.Remove(makeKey(item.SpaceID, al, item.CollectionID, item.ID)) _ = m.cachePublished.Remove(makeKey(item.SpaceID, al, item.CollectionID, item.ID)) } } return err }