Skip to content

Commit 8f98309

Browse files
authored
Catching duplicate attributes, commands and events in the .zap file and fixing them (#1412)
- During import catch all the duplicate endpoint type attributes, commands and events and continue without inserting these rows. - Throw session notifications for each of the above issues. - Upon .zap file save make sure that these warnings go away from the session notification table. - Add tests for the above. - Minor cleanup. - JIRA: ZAPP-1192
1 parent 5d67834 commit 8f98309

File tree

6 files changed

+964
-41
lines changed

6 files changed

+964
-41
lines changed

src-electron/db/query-impexp.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -847,15 +847,13 @@ ORDER BY
847847
*
848848
* @param {*} db
849849
* @param {*} packageId
850-
* @param {*} endpointTypeId
851850
* @param {*} endpointClusterId may be null if global command
852851
* @param {*} command
853852
* @returns Promise of a command insertion.
854853
*/
855854
async function importCommandForEndpointType(
856855
db,
857856
packageIds,
858-
endpointTypeId,
859857
endpointClusterId,
860858
command
861859
) {
@@ -892,7 +890,7 @@ async function importCommandForEndpointType(
892890
return dbApi.dbInsert(
893891
db,
894892
`
895-
INSERT OR IGNORE INTO ENDPOINT_TYPE_COMMAND
893+
INSERT INTO ENDPOINT_TYPE_COMMAND
896894
( ENDPOINT_TYPE_CLUSTER_REF,
897895
COMMAND_REF,
898896
IS_INCOMING,

src-electron/db/query-session.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ async function getDirtySessionsWithPackages(db) {
7171
let rows = await dbApi.dbAll(
7272
db,
7373
`
74-
SELECT
74+
SELECT
7575
SESSION.SESSION_ID,
7676
SESSION.SESSION_KEY,
7777
SESSION.CREATION_TIME,
@@ -814,6 +814,32 @@ async function getAllSessionKeyValues(db, sessionId) {
814814
})
815815
}
816816

817+
/**
818+
* This function deletes session notifications that are related to duplicate
819+
* endpoint type meta data. This is called when user saves the file because that
820+
* action removes the duplicates.
821+
*
822+
* @param {*} db
823+
* @param {*} sessionId
824+
*/
825+
async function deleteSessionNotificationsForDuplicateEndpointTypeMetaData(
826+
db,
827+
sessionId
828+
) {
829+
await dbApi.dbRemove(
830+
db,
831+
`DELETE FROM
832+
SESSION_NOTICE
833+
WHERE
834+
NOTICE_MESSAGE LIKE '%Duplicate endpoint type%'
835+
AND
836+
NOTICE_MESSAGE LIKE '%Remove duplicates in .zap configuration file and re-open .zap file or just save this .zap file to apply the changes.%'
837+
AND
838+
SESSION_NOTICE.SESSION_REF = ?`,
839+
sessionId
840+
)
841+
}
842+
817843
// exports
818844
exports.getAllSessions = getAllSessions
819845
exports.reloadSession = reloadSession
@@ -851,3 +877,5 @@ exports.getAllSessionPartitionInfoForSession =
851877
getAllSessionPartitionInfoForSession
852878
exports.selectDeviceTypePackageInfoFromDeviceTypeId =
853879
selectDeviceTypePackageInfoFromDeviceTypeId
880+
exports.deleteSessionNotificationsForDuplicateEndpointTypeMetaData =
881+
deleteSessionNotificationsForDuplicateEndpointTypeMetaData

src-electron/importexport/export.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ async function exportDataIntoFile(
186186

187187
await fsp.writeFile(filePath, JSON.stringify(state, null, 2))
188188
await querySession.setSessionClean(db, sessionId)
189+
await querySession.deleteSessionNotificationsForDuplicateEndpointTypeMetaData(
190+
db,
191+
sessionId
192+
)
189193
return filePath
190194
}
191195

src-electron/importexport/import-json.js

Lines changed: 181 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,17 @@ function sortEndpoints(endpoints) {
409409
* @param {*} allZclPackageIds
410410
* @param {*} endpointTypeId
411411
* @param {*} clusters
412+
* @param {*} endpointId
413+
* @param {*} sessionId
412414
*/
413-
async function importClusters(db, allZclPackageIds, endpointTypeId, clusters) {
415+
async function importClusters(
416+
db,
417+
allZclPackageIds,
418+
endpointTypeId,
419+
clusters,
420+
endpointId,
421+
sessionId
422+
) {
414423
let relevantZclPackageIds = allZclPackageIds
415424
// Get all custom xml packages since they will be relevant packages as well.
416425
let packageInfo = await queryPackage.getPackagesByPackageIds(
@@ -450,25 +459,31 @@ async function importClusters(db, allZclPackageIds, endpointTypeId, clusters) {
450459
await importCommands(
451460
db,
452461
relevantZclPackageIds,
453-
endpointTypeId,
454462
endpointClusterId,
455-
clusters[k].commands
463+
clusters[k].commands,
464+
clusters[k],
465+
endpointId,
466+
sessionId
456467
)
457468

458469
await importAttributes(
459470
db,
460471
relevantZclPackageIds,
461-
endpointTypeId,
462472
endpointClusterId,
463473
clusters[k].attributes,
464-
clusters[k]
474+
clusters[k],
475+
endpointId,
476+
sessionId
465477
)
466478

467479
await importEvents(
468480
db,
469481
relevantZclPackageIds,
470482
endpointClusterId,
471-
clusters[k].events
483+
clusters[k].events,
484+
clusters[k],
485+
endpointId,
486+
sessionId
472487
)
473488
}
474489
}
@@ -478,26 +493,66 @@ async function importClusters(db, allZclPackageIds, endpointTypeId, clusters) {
478493
* Imports the list of commands from a cluster
479494
* @param {*} db
480495
* @param {*} allZclPackageIds
481-
* @param {*} endpointTypeId
482496
* @param {*} endpointClusterId
483497
* @param {*} commands
498+
* @param {*} cluster
499+
* @param {*} endpointId
500+
* @param {*} sessionId
484501
*/
485502
async function importCommands(
486503
db,
487504
allZclPackageIds,
488-
endpointTypeId,
489505
endpointClusterId,
490-
commands
506+
commands,
507+
cluster,
508+
endpointId,
509+
sessionId
491510
) {
492511
if (commands) {
493-
for (let l = 0; l < commands.length; l++) {
494-
await queryImpexp.importCommandForEndpointType(
495-
db,
496-
allZclPackageIds,
497-
endpointTypeId,
498-
endpointClusterId,
499-
commands[l]
500-
)
512+
for (const command of commands) {
513+
try {
514+
await queryImpexp.importCommandForEndpointType(
515+
db,
516+
allZclPackageIds,
517+
endpointClusterId,
518+
command
519+
)
520+
} catch (err) {
521+
if (err.code === 'SQLITE_CONSTRAINT') {
522+
querySessionNotice.setNotification(
523+
db,
524+
'WARNING',
525+
"Duplicate endpoint type command '" +
526+
command.name +
527+
"' for " +
528+
cluster.name +
529+
' cluster on endpoint ' +
530+
endpointId +
531+
'. Remove duplicates in .zap configuration file and re-open .zap file' +
532+
' or just save this .zap file to apply the changes.',
533+
sessionId,
534+
1,
535+
0
536+
)
537+
env.logWarning(
538+
"Duplicate endpoint type command '" +
539+
command.name +
540+
"' for " +
541+
cluster.name +
542+
' cluster on endpoint ' +
543+
endpointId +
544+
'. Remove duplicates in .zap configuration file and re-open .zap file' +
545+
' or just save this .zap file to apply the changes.'
546+
)
547+
} else {
548+
// Handle other errors
549+
env.logError(
550+
'Unexpected error when inserting into endpoint type command table:',
551+
err.message
552+
)
553+
throw err
554+
}
555+
}
501556
}
502557
}
503558
}
@@ -506,28 +561,67 @@ async function importCommands(
506561
* Imports the list of attributes from a cluster
507562
* @param {*} db
508563
* @param {*} allZclPackageIds
509-
* @param {*} endpointTypeId
510564
* @param {*} endpointClusterId
511565
* @param {*} attributes
512566
* @param {*} cluster
567+
* @param {*} endpointId
568+
* @param {*} sessionId
513569
*/
514570
async function importAttributes(
515571
db,
516572
allZclPackageIds,
517-
endpointTypeId,
518573
endpointClusterId,
519574
attributes,
520-
cluster
575+
cluster,
576+
endpointId,
577+
sessionId
521578
) {
522579
if (attributes) {
523-
for (let m = 0; m < attributes.length; m++) {
524-
await queryImpexp.importAttributeForEndpointType(
525-
db,
526-
allZclPackageIds,
527-
endpointClusterId,
528-
attributes[m],
529-
cluster
530-
)
580+
for (const attribute of attributes) {
581+
try {
582+
await queryImpexp.importAttributeForEndpointType(
583+
db,
584+
allZclPackageIds,
585+
endpointClusterId,
586+
attribute,
587+
cluster
588+
)
589+
} catch (err) {
590+
if (err.code === 'SQLITE_CONSTRAINT') {
591+
querySessionNotice.setNotification(
592+
db,
593+
'WARNING',
594+
"Duplicate endpoint type attribute '" +
595+
attribute.name +
596+
"' for " +
597+
cluster.name +
598+
' cluster on endpoint ' +
599+
endpointId +
600+
'. Remove duplicates in .zap configuration file and re-open .zap file' +
601+
' or just save this .zap file to apply the changes.',
602+
sessionId,
603+
1,
604+
0
605+
)
606+
env.logWarning(
607+
"Duplicate endpoint type attribute '" +
608+
attribute.name +
609+
"' for " +
610+
cluster.name +
611+
' cluster on endpoint ' +
612+
endpointId +
613+
'. Remove duplicates in .zap configuration file and re-open .zap file' +
614+
' or just save this .zap file to apply the changes.'
615+
)
616+
} else {
617+
// Handle other errors
618+
env.logError(
619+
'Unexpected error when inserting into endpoint type attribute table:',
620+
err.message
621+
)
622+
throw err
623+
}
624+
}
531625
}
532626
}
533627
}
@@ -538,16 +632,64 @@ async function importAttributes(
538632
* @param {*} allZclPackageIds
539633
* @param {*} endpointClusterId
540634
* @param {*} events
635+
* @param {*} cluster
636+
* @param {*} endpointId
637+
* @param {*} sessionId
541638
*/
542-
async function importEvents(db, allZclPackageIds, endpointClusterId, events) {
639+
async function importEvents(
640+
db,
641+
allZclPackageIds,
642+
endpointClusterId,
643+
events,
644+
cluster,
645+
endpointId,
646+
sessionId
647+
) {
543648
if (events) {
544-
for (let n = 0; n < events.length; n++) {
545-
await queryImpexp.importEventForEndpointType(
546-
db,
547-
allZclPackageIds,
548-
endpointClusterId,
549-
events[n]
550-
)
649+
for (const event of events) {
650+
try {
651+
await queryImpexp.importEventForEndpointType(
652+
db,
653+
allZclPackageIds,
654+
endpointClusterId,
655+
event
656+
)
657+
} catch (err) {
658+
if (err.code === 'SQLITE_CONSTRAINT') {
659+
querySessionNotice.setNotification(
660+
db,
661+
'WARNING',
662+
"Duplicate endpoint type event '" +
663+
event.name +
664+
"' for " +
665+
cluster.name +
666+
' cluster on endpoint ' +
667+
endpointId +
668+
'. Remove duplicates in .zap configuration file and re-open .zap file' +
669+
' or just save this .zap file to apply the changes.',
670+
sessionId,
671+
1,
672+
0
673+
)
674+
env.logWarning(
675+
"Duplicate endpoint type event '" +
676+
event.name +
677+
"' for " +
678+
cluster.name +
679+
' cluster on endpoint ' +
680+
endpointId +
681+
'. Remove duplicates in .zap configuration file and re-open .zap file' +
682+
' or just save this .zap file to apply the changes.'
683+
)
684+
} else {
685+
// Handle other errors
686+
env.logError(
687+
'Unexpected error when inserting into endpoint type event table:',
688+
err.message
689+
)
690+
throw err
691+
}
692+
}
551693
}
552694
}
553695
}
@@ -1393,7 +1535,9 @@ async function importEndpointTypes(
13931535
db,
13941536
allZclPackageIds,
13951537
endpointTypeId,
1396-
endpointTypes[i].clusters
1538+
endpointTypes[i].clusters,
1539+
endpointId,
1540+
sessionId
13971541
)
13981542

13991543
/**

0 commit comments

Comments
 (0)