3
0

Fix dal schema alterations not presenting/reloading revision models

This commit is contained in:
Tomaž Jerman 2023-12-12 15:27:48 +01:00
parent 3e1d7bd42b
commit 33821ddd9f
14 changed files with 185 additions and 76 deletions

View File

@ -183,7 +183,7 @@ export default {
},
batch: {
type: String,
type: Array,
required: false,
default: undefined,
},
@ -217,8 +217,8 @@ export default {
watch: {
batch: {
handler (batch) {
if (batch) {
this.load(batch)
if (batch && batch.length) {
this.load(...batch)
}
},
},
@ -243,7 +243,7 @@ export default {
for (const a of alteration) {
a.processing = false
}
this.load(this.batch)
this.load(...this.batch)
this.processing = false
})
},
@ -266,13 +266,13 @@ export default {
for (const a of alteration) {
a.processing = false
}
this.load(this.batch)
this.load(...this.batch)
this.processing = false
})
},
async load (batchID) {
if (!batchID) {
async load (...batchID) {
if (!batchID || (batchID && !batchID.length)) {
this.alterations = []
return
}

View File

@ -885,11 +885,12 @@ export default {
// Check if module has Alterations to resolve
this.dalSchemaAlterations.batchID = undefined
for (const i of this.module.issues) {
if (i.meta.batchID) {
this.dalSchemaAlterations.batchID = i.meta.batchID
break
}
// Pull all batchIDs as they can differ in cases where a related resource
// also requires alterations.
// @todo this should probably perhaps change but I'm not entirely sure how
const aux = (this.module.issues || []).map(({ meta }) => meta.batchID).filter(b => b)
if (aux.length > 0) {
this.dalSchemaAlterations.batchID = aux
}
},

View File

@ -2529,6 +2529,8 @@ export default class System {
const {
alterationID,
batchID,
resource,
resourceType,
kind,
deleted,
completed,
@ -2543,6 +2545,8 @@ export default class System {
cfg.params = {
alterationID,
batchID,
resource,
resourceType,
kind,
deleted,
completed,

View File

@ -81,10 +81,9 @@ func (a recordsLookupArgs) GetRecord() (bool, uint64, *types.Record) {
// Lookup function Compose record lookup
//
// expects implementation of lookup function:
//
// func (h recordsHandler) lookup(ctx context.Context, args *recordsLookupArgs) (results *recordsLookupResults, err error) {
// return
// }
// func (h recordsHandler) lookup(ctx context.Context, args *recordsLookupArgs) (results *recordsLookupResults, err error) {
// return
// }
func (h recordsHandler) Lookup() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsLookup",
@ -256,10 +255,9 @@ func (a recordsSearchArgs) GetNamespace() (bool, uint64, string, *types.Namespac
// Search function Compose records search
//
// expects implementation of search function:
//
// func (h recordsHandler) search(ctx context.Context, args *recordsSearchArgs) (results *recordsSearchResults, err error) {
// return
// }
// func (h recordsHandler) search(ctx context.Context, args *recordsSearchArgs) (results *recordsSearchResults, err error) {
// return
// }
func (h recordsHandler) Search() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsSearch",
@ -510,10 +508,9 @@ func (a recordsFirstArgs) GetNamespace() (bool, uint64, string, *types.Namespace
// First function Compose record lookup (first created)
//
// expects implementation of first function:
//
// func (h recordsHandler) first(ctx context.Context, args *recordsFirstArgs) (results *recordsFirstResults, err error) {
// return
// }
// func (h recordsHandler) first(ctx context.Context, args *recordsFirstArgs) (results *recordsFirstResults, err error) {
// return
// }
func (h recordsHandler) First() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsFirst",
@ -640,10 +637,9 @@ func (a recordsLastArgs) GetNamespace() (bool, uint64, string, *types.Namespace)
// Last function Compose record lookup (last created)
//
// expects implementation of last function:
//
// func (h recordsHandler) last(ctx context.Context, args *recordsLastArgs) (results *recordsLastResults, err error) {
// return
// }
// func (h recordsHandler) last(ctx context.Context, args *recordsLastArgs) (results *recordsLastResults, err error) {
// return
// }
func (h recordsHandler) Last() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsLast",
@ -796,10 +792,9 @@ func (a recordsEachArgs) GetNamespace() (bool, uint64, string, *types.Namespace)
// Each function Compose records
//
// expects implementation of each function:
//
// func (h recordsHandler) each(ctx context.Context, args *recordsEachArgs) (results *recordsEachResults, err error) {
// return
// }
// func (h recordsHandler) each(ctx context.Context, args *recordsEachArgs) (results *recordsEachResults, err error) {
// return
// }
func (h recordsHandler) Each() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsEach",
@ -964,10 +959,9 @@ func (a recordsNewArgs) GetNamespace() (bool, uint64, string, *types.Namespace)
// New function Compose record maker
//
// expects implementation of new function:
//
// func (h recordsHandler) new(ctx context.Context, args *recordsNewArgs) (results *recordsNewResults, err error) {
// return
// }
// func (h recordsHandler) new(ctx context.Context, args *recordsNewArgs) (results *recordsNewResults, err error) {
// return
// }
func (h recordsHandler) New() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsNew",
@ -1078,10 +1072,9 @@ type (
// Validate function Compose record validator
//
// expects implementation of validate function:
//
// func (h recordsHandler) validate(ctx context.Context, args *recordsValidateArgs) (results *recordsValidateResults, err error) {
// return
// }
// func (h recordsHandler) validate(ctx context.Context, args *recordsValidateArgs) (results *recordsValidateResults, err error) {
// return
// }
func (h recordsHandler) Validate() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsValidate",
@ -1159,10 +1152,9 @@ type (
// Create function Compose record create
//
// expects implementation of create function:
//
// func (h recordsHandler) create(ctx context.Context, args *recordsCreateArgs) (results *recordsCreateResults, err error) {
// return
// }
// func (h recordsHandler) create(ctx context.Context, args *recordsCreateArgs) (results *recordsCreateResults, err error) {
// return
// }
func (h recordsHandler) Create() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsCreate",
@ -1237,10 +1229,9 @@ type (
// Update function Compose record update
//
// expects implementation of update function:
//
// func (h recordsHandler) update(ctx context.Context, args *recordsUpdateArgs) (results *recordsUpdateResults, err error) {
// return
// }
// func (h recordsHandler) update(ctx context.Context, args *recordsUpdateArgs) (results *recordsUpdateResults, err error) {
// return
// }
func (h recordsHandler) Update() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsUpdate",
@ -1337,10 +1328,9 @@ func (a recordsDeleteArgs) GetRecord() (bool, uint64, *types.Record) {
// Delete function Compose record delete
//
// expects implementation of delete function:
//
// func (h recordsHandler) delete(ctx context.Context, args *recordsDeleteArgs) (err error) {
// return
// }
// func (h recordsHandler) delete(ctx context.Context, args *recordsDeleteArgs) (err error) {
// return
// }
func (h recordsHandler) Delete() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsDelete",
@ -1464,10 +1454,9 @@ func (a recordsReportArgs) GetNamespace() (bool, uint64, string, *types.Namespac
// Report function Report
//
// expects implementation of report function:
//
// func (h recordsHandler) report(ctx context.Context, args *recordsReportArgs) (results *recordsReportResults, err error) {
// return
// }
// func (h recordsHandler) report(ctx context.Context, args *recordsReportArgs) (results *recordsReportResults, err error) {
// return
// }
func (h recordsHandler) Report() *atypes.Function {
return &atypes.Function{
Ref: "composeRecordsReport",

View File

@ -310,6 +310,7 @@ func (svc module) procDal(m *types.Module) {
}
m.Issues = svc.dal.SearchModelIssues(m.ID)
m.Issues = append(m.Issues, svc.dal.SearchResourceIssues("corteza::system:revision", m.RbacResource())...)
if len(m.Issues) == 0 {
m.Issues = nil
}

View File

@ -45,6 +45,19 @@ func (svc *service) SearchModelIssues(resourceID uint64) (out []Issue) {
return svc.modelIssues[resourceID]
}
func (svc *service) SearchResourceIssues(resourceType, resource string) (out []Issue) {
var m *Model
for _, ax := range svc.models {
m = ax.FindByResourceIdent(resourceType, resource)
}
if m == nil {
return
}
return svc.modelIssues[m.ResourceID]
}
func (svc *service) hasConnectionIssues(connectionID uint64) bool {
return len(svc.SearchConnectionIssues(connectionID)) > 0
}

View File

@ -64,6 +64,7 @@ type (
SearchConnectionIssues(connectionID uint64) (out []Issue)
SearchModelIssues(resourceID uint64) (out []Issue)
SearchResourceIssues(resourceType, resource string) (out []Issue)
}
)
@ -794,6 +795,41 @@ func (svc *service) ApplyAlteration(ctx context.Context, alts ...*Alteration) (e
return
}
altsIndexed := make(map[uint64]map[string]map[string][]*Alteration)
for _, a := range alts {
if _, ok := altsIndexed[a.ConnectionID]; !ok {
altsIndexed[a.ConnectionID] = make(map[string]map[string][]*Alteration)
}
if _, ok := altsIndexed[a.ConnectionID][a.ResourceType]; !ok {
altsIndexed[a.ConnectionID][a.ResourceType] = make(map[string][]*Alteration)
}
altsIndexed[a.ConnectionID][a.ResourceType][a.Resource] = append(altsIndexed[a.ConnectionID][a.ResourceType][a.Resource], a)
}
var auxErrs []error
for _, byCon := range altsIndexed {
for _, byRt := range byCon {
for _, byR := range byRt {
auxErrs, err = svc.applyAlteration(ctx, byR...)
if err != nil {
return
}
errs = append(errs, auxErrs...)
}
}
}
return
}
func (svc *service) applyAlteration(ctx context.Context, alts ...*Alteration) (errs []error, err error) {
if len(alts) == 0 {
return
}
var (
connectionID = alts[0].ConnectionID
resource = alts[0].Resource

View File

@ -831,8 +831,8 @@ func DalSchemaAlterationFilter(d drivers.Dialect, f systemType.DalSchemaAlterati
ee = append(ee, goqu.C("id").In(f.AlterationID))
}
if f.BatchID > 0 {
ee = append(ee, goqu.C("batch_id").Eq(f.BatchID))
if len(f.BatchID) > 0 {
ee = append(ee, goqu.C("batch_id").In(f.BatchID))
}
return ee, f, err

View File

@ -86,7 +86,7 @@ dal_schema_alteration: {
resource: {goType: "[]string", ident: "resource" }
resourceType: {goType: "string", ident: "resourceType", storeIdent: "resource_type" }
alteration_id: {goType: "[]uint64", ident: "alterationID", storeIdent: "id" }
batch_id: {goType: "uint64", ident: "batchID" }
batch_id: {goType: "[]uint64", ident: "batchID" }
kind: {}
deleted: {goType: "filter.State", storeIdent: "deleted_at"}
completed: {goType: "filter.State", storeIdent: "completed_at"}

View File

@ -932,8 +932,14 @@ endpoints:
type: "[]string"
title: Filter by alteration ID
- name: batchID
type: "uint64"
type: "[]string"
title: Filter by batch ID
- name: resource
type: "[]string"
title: Search by resource
- name: resourceType
type: string
title: Search by resource type
- type: string
name: kind
title: Search by kind

View File

@ -5,6 +5,7 @@ import (
"github.com/cortezaproject/corteza/server/pkg/api"
"github.com/cortezaproject/corteza/server/pkg/filter"
"github.com/cortezaproject/corteza/server/pkg/id"
"github.com/cortezaproject/corteza/server/system/rest/request"
"github.com/cortezaproject/corteza/server/system/service"
"github.com/cortezaproject/corteza/server/system/types"
@ -60,8 +61,10 @@ func (ctrl DalSchemaAlteration) List(ctx context.Context, r *request.DalSchemaAl
f = types.DalSchemaAlterationFilter{
AlterationID: r.AlterationID,
BatchID: r.BatchID,
BatchID: id.Uints(r.BatchID...),
Kind: r.Kind,
Resource: r.Resource,
ResourceType: r.ResourceType,
Deleted: filter.State(r.Deleted),
Dismissed: filter.State(r.Dismissed),

View File

@ -42,7 +42,17 @@ type (
// BatchID GET parameter
//
// Filter by batch ID
BatchID uint64 `json:",string"`
BatchID []string
// Resource GET parameter
//
// Search by resource
Resource []string
// ResourceType GET parameter
//
// Search by resource type
ResourceType string
// Kind GET parameter
//
@ -102,6 +112,8 @@ func (r DalSchemaAlterationList) Auditable() map[string]interface{} {
return map[string]interface{}{
"alterationID": r.AlterationID,
"batchID": r.BatchID,
"resource": r.Resource,
"resourceType": r.ResourceType,
"kind": r.Kind,
"deleted": r.Deleted,
"completed": r.Completed,
@ -116,10 +128,20 @@ func (r DalSchemaAlterationList) GetAlterationID() []string {
}
// Auditable returns all auditable/loggable parameters
func (r DalSchemaAlterationList) GetBatchID() uint64 {
func (r DalSchemaAlterationList) GetBatchID() []string {
return r.BatchID
}
// Auditable returns all auditable/loggable parameters
func (r DalSchemaAlterationList) GetResource() []string {
return r.Resource
}
// Auditable returns all auditable/loggable parameters
func (r DalSchemaAlterationList) GetResourceType() string {
return r.ResourceType
}
// Auditable returns all auditable/loggable parameters
func (r DalSchemaAlterationList) GetKind() string {
return r.Kind
@ -163,8 +185,30 @@ func (r *DalSchemaAlterationList) Fill(req *http.Request) (err error) {
return err
}
}
if val, ok := tmp["batchID"]; ok && len(val) > 0 {
r.BatchID, err = payload.ParseUint64(val[0]), nil
if val, ok := tmp["batchID[]"]; ok {
r.BatchID, err = val, nil
if err != nil {
return err
}
} else if val, ok := tmp["batchID"]; ok {
r.BatchID, err = val, nil
if err != nil {
return err
}
}
if val, ok := tmp["resource[]"]; ok {
r.Resource, err = val, nil
if err != nil {
return err
}
} else if val, ok := tmp["resource"]; ok {
r.Resource, err = val, nil
if err != nil {
return err
}
}
if val, ok := tmp["resourceType"]; ok && len(val) > 0 {
r.ResourceType, err = val[0], nil
if err != nil {
return err
}

View File

@ -402,25 +402,37 @@ func (svc dalSchemaAlteration) toPkgAlterations(ctx context.Context, aa ...*type
}
func (svc dalSchemaAlteration) reloadAlteredModels(ctx context.Context, s store.Storer, alts types.DalSchemaAlterationSet) (err error) {
if len(alts) == 0 {
return
// Skip any models whish were already reloaded by some alterations.
// These might be mixed up so we'll need to do it like so.
processed := make(map[string]bool, 3)
mkKey := func(a *types.DalSchemaAlteration) string {
return fmt.Sprintf("%s;%s", a.ResourceType, a.Resource)
}
// @todo consider lifting this constraint and handle arbitrary sets of alterations
for _, a := range alts {
if a.Resource != alts[0].Resource {
panic("reloadAlteredModels requires all alterations to be for the same resource")
k := mkKey(a)
if processed[k] {
continue
}
processed[k] = true
err = svc.reloadAlteredModel(ctx, s, a)
if err != nil {
return
}
}
alt := alts[0]
return
}
func (svc dalSchemaAlteration) reloadAlteredModel(ctx context.Context, s store.Storer, alt *types.DalSchemaAlteration) (err error) {
// Fetch current alterations to see if there are any left over
_, f, err := store.SearchDalSchemaAlterations(ctx, s, types.DalSchemaAlterationFilter{
Resource: []string{alt.Resource},
Deleted: filter.StateExcluded,
Completed: filter.StateExcluded,
Dismissed: filter.StateExcluded,
Resource: []string{alt.Resource},
ResourceType: alt.ResourceType,
Deleted: filter.StateExcluded,
Completed: filter.StateExcluded,
Dismissed: filter.StateExcluded,
Paging: filter.Paging{
IncTotal: true,

View File

@ -49,7 +49,7 @@ type (
DalSchemaAlterationFilter struct {
AlterationID []string `json:"alterationID"`
BatchID uint64 `json:"batchID,string"`
BatchID []uint64 `json:"batchID,string"`
Kind string `json:"kind"`
Resource []string `json:"resource"`
ResourceType string `json:"resourceType"`