Fix resource activity log store yaml

This commit is contained in:
Vivek Patel
2022-05-09 16:39:52 +05:30
parent d5436ccecb
commit e7ed1d8271
4 changed files with 11 additions and 391 deletions
+1 -1
View File
@@ -675,7 +675,6 @@ endpoints:
authentication: []
imports:
- github.com/cortezaproject/corteza-server/pkg/label
- github.com/cortezaproject/corteza-server/pkg/locale
- github.com/cortezaproject/corteza-server/compose/types
parameters:
path:
@@ -953,6 +952,7 @@ endpoints:
imports:
- sqlxTypes github.com/jmoiron/sqlx/types
- github.com/cortezaproject/corteza-server/pkg/label
- github.com/cortezaproject/corteza-server/pkg/locale
- time
parameters:
path:
+3 -338
View File
@@ -14,9 +14,7 @@ import (
"github.com/Masterminds/squirrel"
"github.com/cortezaproject/corteza-server/pkg/discovery/types"
"github.com/cortezaproject/corteza-server/pkg/errors"
"github.com/cortezaproject/corteza-server/pkg/filter"
"github.com/cortezaproject/corteza-server/store"
"github.com/cortezaproject/corteza-server/store/rdbms/builders"
)
var _ = errors.Is
@@ -38,195 +36,11 @@ func (s Store) SearchResourceActivityLogs(ctx context.Context, f types.ResourceA
return err
}
// Paging enabled
// {search: {enablePaging:true}}
// Cleanup unwanted cursor values (only relevant is f.PageCursor, next&prev are reset and returned)
f.PrevPage, f.NextPage = nil, nil
if f.PageCursor != nil {
// Page cursor exists so we need to validate it against used sort
// To cover the case when paging cursor is set but sorting is empty, we collect the sorting instructions
// from the cursor.
// This (extracted sorting info) is then returned as part of response
if f.Sort, err = f.PageCursor.Sort(f.Sort); err != nil {
return err
}
}
// Make sure results are always sorted at least by primary keys
if f.Sort.Get("id") == nil {
f.Sort = append(f.Sort, &filter.SortExpr{
Column: "id",
Descending: f.Sort.LastDescending(),
})
}
// Cloned sorting instructions for the actual sorting
// Original are passed to the fetchFullPageOfUsers fn used for cursor creation so it MUST keep the initial
// direction information
sort := f.Sort.Clone()
// When cursor for a previous page is used it's marked as reversed
// This tells us to flip the descending flag on all used sort keys
if f.PageCursor != nil && f.PageCursor.ROrder {
sort.Reverse()
}
// Apply sorting expr from filter to query
if q, err = setOrderBy(q, sort, s.sortableResourceActivityLogColumns(), s.Config().SqlSortHandler); err != nil {
return err
}
set, f.PrevPage, f.NextPage, err = s.fetchFullPageOfResourceActivityLogs(
ctx,
q, f.Sort, f.PageCursor,
f.Limit,
nil,
func(cur *filter.PagingCursor) squirrel.Sqlizer {
return builders.CursorCondition(cur, nil)
},
)
if err != nil {
return err
}
f.PageCursor = nil
return nil
set, err = s.QueryResourceActivityLogs(ctx, q, nil)
return err
}()
}
// fetchFullPageOfResourceActivityLogs collects all requested results.
//
// Function applies:
// - cursor conditions (where ...)
// - limit
//
// Main responsibility of this function is to perform additional sequential queries in case when not enough results
// are collected due to failed check on a specific row (by check fn).
//
// Function then moves cursor to the last item fetched
func (s Store) fetchFullPageOfResourceActivityLogs(
ctx context.Context,
q squirrel.SelectBuilder,
sort filter.SortExprSet,
cursor *filter.PagingCursor,
reqItems uint,
check func(*types.ResourceActivity) (bool, error),
cursorCond func(*filter.PagingCursor) squirrel.Sqlizer,
) (set []*types.ResourceActivity, prev, next *filter.PagingCursor, err error) {
var (
aux []*types.ResourceActivity
// When cursor for a previous page is used it's marked as reversed
// This tells us to flip the descending flag on all used sort keys
reversedOrder = cursor != nil && cursor.ROrder
// copy of the select builder
tryQuery squirrel.SelectBuilder
// Copy no. of required items to limit
// Limit will change when doing subsequent queries to fill
// the set with all required items
limit = reqItems
// cursor to prev. page is only calculated when cursor is used
hasPrev = cursor != nil
// next cursor is calculated when there are more pages to come
hasNext bool
)
set = make([]*types.ResourceActivity, 0, DefaultSliceCapacity)
for try := 0; try < MaxRefetches; try++ {
if cursor != nil {
tryQuery = q.Where(cursorCond(cursor))
} else {
tryQuery = q
}
if limit > 0 {
// fetching + 1 so we know if there are more items
// we can fetch (next-page cursor)
tryQuery = tryQuery.Limit(uint64(limit + 1))
}
if aux, err = s.QueryResourceActivityLogs(ctx, tryQuery, check); err != nil {
return nil, nil, nil, err
}
if len(aux) == 0 {
// nothing fetched
break
}
// append fetched items
set = append(set, aux...)
if reqItems == 0 {
// no max requested items specified, break out
break
}
collected := uint(len(set))
if reqItems > collected {
// not enough items fetched, try again with adjusted limit
limit = reqItems - collected
if limit < MinEnsureFetchLimit {
// In case limit is set very low and we've missed records in the first fetch,
// make sure next fetch limit is a bit higher
limit = MinEnsureFetchLimit
}
// Update cursor so that it points to the last item fetched
cursor = s.collectResourceActivityLogCursorValues(set[collected-1], sort...)
// Copy reverse flag from sorting
cursor.LThen = sort.Reversed()
continue
}
if reqItems < collected {
set = set[:reqItems]
hasNext = true
}
break
}
collected := len(set)
if collected == 0 {
return nil, nil, nil, nil
}
if reversedOrder {
// Fetched set needs to be reversed because we've forced a descending order to get the previous page
for i, j := 0, collected-1; i < j; i, j = i+1, j-1 {
set[i], set[j] = set[j], set[i]
}
// when in reverse-order rules on what cursor to return change
hasPrev, hasNext = hasNext, hasPrev
}
if hasPrev {
prev = s.collectResourceActivityLogCursorValues(set[0], sort...)
prev.ROrder = true
prev.LThen = !sort.Reversed()
}
if hasNext {
next = s.collectResourceActivityLogCursorValues(set[collected-1], sort...)
next.LThen = sort.Reversed()
}
return set, prev, next, nil
}
// QueryResourceActivityLogs queries the database, converts and checks each row and
// returns collected set
//
@@ -271,14 +85,6 @@ func (s Store) QueryResourceActivityLogs(
return set, nil
}
// LookupResourceActivityLogByID searches for corteza resource activity by ID
// It returns corteza resource activity even if deleted
func (s Store) LookupResourceActivityLogByID(ctx context.Context, id uint64) (*types.ResourceActivity, error) {
return s.execLookupResourceActivityLog(ctx, squirrel.Eq{
s.preprocessColumn("ral.id", ""): store.PreprocessValue(id, ""),
})
}
// CreateResourceActivityLog creates one or more rows in resource_activity_log table
func (s Store) CreateResourceActivityLog(ctx context.Context, rr ...*types.ResourceActivity) (err error) {
for _, res := range rr {
@@ -296,72 +102,6 @@ func (s Store) CreateResourceActivityLog(ctx context.Context, rr ...*types.Resou
return
}
// UpdateResourceActivityLog updates one or more existing rows in resource_activity_log
func (s Store) UpdateResourceActivityLog(ctx context.Context, rr ...*types.ResourceActivity) error {
return s.partialResourceActivityLogUpdate(ctx, nil, rr...)
}
// partialResourceActivityLogUpdate updates one or more existing rows in resource_activity_log
func (s Store) partialResourceActivityLogUpdate(ctx context.Context, onlyColumns []string, rr ...*types.ResourceActivity) (err error) {
for _, res := range rr {
err = s.checkResourceActivityLogConstraints(ctx, res)
if err != nil {
return err
}
err = s.execUpdateResourceActivityLogs(
ctx,
squirrel.Eq{
s.preprocessColumn("ral.id", ""): store.PreprocessValue(res.ID, ""),
},
s.internalResourceActivityLogEncoder(res).Skip("id").Only(onlyColumns...))
if err != nil {
return err
}
}
return
}
// UpsertResourceActivityLog updates one or more existing rows in resource_activity_log
func (s Store) UpsertResourceActivityLog(ctx context.Context, rr ...*types.ResourceActivity) (err error) {
for _, res := range rr {
err = s.checkResourceActivityLogConstraints(ctx, res)
if err != nil {
return err
}
err = s.execUpsertResourceActivityLogs(ctx, s.internalResourceActivityLogEncoder(res))
if err != nil {
return err
}
}
return nil
}
// DeleteResourceActivityLog Deletes one or more rows from resource_activity_log table
func (s Store) DeleteResourceActivityLog(ctx context.Context, rr ...*types.ResourceActivity) (err error) {
for _, res := range rr {
err = s.execDeleteResourceActivityLogs(ctx, squirrel.Eq{
s.preprocessColumn("ral.id", ""): store.PreprocessValue(res.ID, ""),
})
if err != nil {
return err
}
}
return nil
}
// DeleteResourceActivityLogByID Deletes row from the resource_activity_log table
func (s Store) DeleteResourceActivityLogByID(ctx context.Context, ID uint64) error {
return s.execDeleteResourceActivityLogs(ctx, squirrel.Eq{
s.preprocessColumn("ral.id", ""): store.PreprocessValue(ID, ""),
})
}
// TruncateResourceActivityLogs Deletes all rows from the resource_activity_log table
func (s Store) TruncateResourceActivityLogs(ctx context.Context) error {
return s.Truncate(ctx, s.resourceActivityLogTable())
@@ -392,32 +132,6 @@ func (s Store) execCreateResourceActivityLogs(ctx context.Context, payload store
return s.Exec(ctx, s.InsertBuilder(s.resourceActivityLogTable()).SetMap(payload))
}
// execUpdateResourceActivityLogs updates all matched (by cnd) rows in resource_activity_log with given data
func (s Store) execUpdateResourceActivityLogs(ctx context.Context, cnd squirrel.Sqlizer, set store.Payload) error {
return s.Exec(ctx, s.UpdateBuilder(s.resourceActivityLogTable("ral")).Where(cnd).SetMap(set))
}
// execUpsertResourceActivityLogs inserts new or updates matching (by-primary-key) rows in resource_activity_log with given data
func (s Store) execUpsertResourceActivityLogs(ctx context.Context, set store.Payload) error {
upsert, err := s.config.UpsertBuilder(
s.config,
s.resourceActivityLogTable(),
set,
s.preprocessColumn("id", ""),
)
if err != nil {
return err
}
return s.Exec(ctx, upsert)
}
// execDeleteResourceActivityLogs Deletes all matched (by cnd) rows in resource_activity_log with given data
func (s Store) execDeleteResourceActivityLogs(ctx context.Context, cnd squirrel.Sqlizer) error {
return s.Exec(ctx, s.DeleteBuilder(s.resourceActivityLogTable("ral")).Where(cnd))
}
func (s Store) internalResourceActivityLogRowScanner(row rowScanner) (res *types.ResourceActivity, err error) {
res = &types.ResourceActivity{}
@@ -475,16 +189,7 @@ func (Store) resourceActivityLogColumns(aa ...string) []string {
}
}
// {true true false true true false}
// sortableResourceActivityLogColumns returns all ResourceActivityLog columns flagged as sortable
//
// With optional string arg, all columns are returned aliased
func (Store) sortableResourceActivityLogColumns() map[string]string {
return map[string]string{
"id": "id",
}
}
// {true true false false false false}
// internalResourceActivityLogEncoder encodes fields from types.ResourceActivity to store.Payload (map)
//
@@ -501,46 +206,6 @@ func (s Store) internalResourceActivityLogEncoder(res *types.ResourceActivity) s
}
}
// collectResourceActivityLogCursorValues collects values from the given resource that and sets them to the cursor
// to be used for pagination
//
// Values that are collected must come from sortable, unique or primary columns/fields
// At least one of the collected columns must be flagged as unique, otherwise fn appends primary keys at the end
//
// Known issue:
// when collecting cursor values for query that sorts by unique column with partial index (ie: unique handle on
// undeleted items)
func (s Store) collectResourceActivityLogCursorValues(res *types.ResourceActivity, cc ...*filter.SortExpr) *filter.PagingCursor {
var (
cursor = &filter.PagingCursor{LThen: filter.SortExprSet(cc).Reversed()}
hasUnique bool
// All known primary key columns
pkId bool
collect = func(cc ...*filter.SortExpr) {
for _, c := range cc {
switch c.Column {
case "id":
cursor.Set(c.Column, res.ID, c.Descending)
pkId = true
}
}
}
)
collect(cc...)
if !hasUnique || !(pkId && true) {
collect(&filter.SortExpr{Column: "id", Descending: false})
}
return cursor
}
// checkResourceActivityLogConstraints performs lookups (on valid) resource to check if any of the values on unique fields
// already exists in the store
//
-34
View File
@@ -16,17 +16,9 @@ import (
type (
ResourceActivityLogs interface {
SearchResourceActivityLogs(ctx context.Context, f types.ResourceActivityFilter) (types.ResourceActivitySet, types.ResourceActivityFilter, error)
LookupResourceActivityLogByID(ctx context.Context, id uint64) (*types.ResourceActivity, error)
CreateResourceActivityLog(ctx context.Context, rr ...*types.ResourceActivity) error
UpdateResourceActivityLog(ctx context.Context, rr ...*types.ResourceActivity) error
UpsertResourceActivityLog(ctx context.Context, rr ...*types.ResourceActivity) error
DeleteResourceActivityLog(ctx context.Context, rr ...*types.ResourceActivity) error
DeleteResourceActivityLogByID(ctx context.Context, ID uint64) error
TruncateResourceActivityLogs(ctx context.Context) error
}
)
@@ -39,37 +31,11 @@ func SearchResourceActivityLogs(ctx context.Context, s ResourceActivityLogs, f t
return s.SearchResourceActivityLogs(ctx, f)
}
// LookupResourceActivityLogByID searches for corteza resource activity by ID
// It returns corteza resource activity even if deleted
func LookupResourceActivityLogByID(ctx context.Context, s ResourceActivityLogs, id uint64) (*types.ResourceActivity, error) {
return s.LookupResourceActivityLogByID(ctx, id)
}
// CreateResourceActivityLog creates one or more ResourceActivityLogs in store
func CreateResourceActivityLog(ctx context.Context, s ResourceActivityLogs, rr ...*types.ResourceActivity) error {
return s.CreateResourceActivityLog(ctx, rr...)
}
// UpdateResourceActivityLog updates one or more (existing) ResourceActivityLogs in store
func UpdateResourceActivityLog(ctx context.Context, s ResourceActivityLogs, rr ...*types.ResourceActivity) error {
return s.UpdateResourceActivityLog(ctx, rr...)
}
// UpsertResourceActivityLog creates new or updates existing one or more ResourceActivityLogs in store
func UpsertResourceActivityLog(ctx context.Context, s ResourceActivityLogs, rr ...*types.ResourceActivity) error {
return s.UpsertResourceActivityLog(ctx, rr...)
}
// DeleteResourceActivityLog Deletes one or more ResourceActivityLogs from store
func DeleteResourceActivityLog(ctx context.Context, s ResourceActivityLogs, rr ...*types.ResourceActivity) error {
return s.DeleteResourceActivityLog(ctx, rr...)
}
// DeleteResourceActivityLogByID Deletes ResourceActivityLog from store
func DeleteResourceActivityLogByID(ctx context.Context, s ResourceActivityLogs, ID uint64) error {
return s.DeleteResourceActivityLogByID(ctx, ID)
}
// TruncateResourceActivityLogs Deletes all ResourceActivityLogs from store
func TruncateResourceActivityLogs(ctx context.Context, s ResourceActivityLogs) error {
return s.TruncateResourceActivityLogs(ctx)
+7 -18
View File
@@ -13,16 +13,6 @@ fields:
- { field: Timestamp, type: "time.Time" }
- { field: Meta, type: "types.JSONText" }
lookups:
- fields: [ ID ]
export: true
description: |-
searches for corteza resource activity by ID
It returns corteza resource activity even if deleted
search:
enableFilterCheckFunction: false
rdbms:
alias: ral
table: resource_activity_log
@@ -31,18 +21,17 @@ rdbms:
Timestamp: { column: ts }
Meta: { column: meta }
create:
export: true
search:
enablePaging: false
enableSorting: false
enableFilterCheckFunction: false
update:
export: true
enable: false
upsert:
export: true
enable: false
delete:
export: true
truncate:
export: true
enable: false