Skip to content

Commit

Permalink
Catching duplicate attributes, commands and events in the .zap file a…
Browse files Browse the repository at this point in the history
…nd fixing them (project-chip#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
  • Loading branch information
brdandu authored Aug 26, 2024
1 parent 5d67834 commit 8f98309
Show file tree
Hide file tree
Showing 6 changed files with 964 additions and 41 deletions.
4 changes: 1 addition & 3 deletions src-electron/db/query-impexp.js
Original file line number Diff line number Diff line change
Expand Up @@ -847,15 +847,13 @@ ORDER BY
*
* @param {*} db
* @param {*} packageId
* @param {*} endpointTypeId
* @param {*} endpointClusterId may be null if global command
* @param {*} command
* @returns Promise of a command insertion.
*/
async function importCommandForEndpointType(
db,
packageIds,
endpointTypeId,
endpointClusterId,
command
) {
Expand Down Expand Up @@ -892,7 +890,7 @@ async function importCommandForEndpointType(
return dbApi.dbInsert(
db,
`
INSERT OR IGNORE INTO ENDPOINT_TYPE_COMMAND
INSERT INTO ENDPOINT_TYPE_COMMAND
( ENDPOINT_TYPE_CLUSTER_REF,
COMMAND_REF,
IS_INCOMING,
Expand Down
30 changes: 29 additions & 1 deletion src-electron/db/query-session.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ async function getDirtySessionsWithPackages(db) {
let rows = await dbApi.dbAll(
db,
`
SELECT
SELECT
SESSION.SESSION_ID,
SESSION.SESSION_KEY,
SESSION.CREATION_TIME,
Expand Down Expand Up @@ -814,6 +814,32 @@ async function getAllSessionKeyValues(db, sessionId) {
})
}

/**
* This function deletes session notifications that are related to duplicate
* endpoint type meta data. This is called when user saves the file because that
* action removes the duplicates.
*
* @param {*} db
* @param {*} sessionId
*/
async function deleteSessionNotificationsForDuplicateEndpointTypeMetaData(
db,
sessionId
) {
await dbApi.dbRemove(
db,
`DELETE FROM
SESSION_NOTICE
WHERE
NOTICE_MESSAGE LIKE '%Duplicate endpoint type%'
AND
NOTICE_MESSAGE LIKE '%Remove duplicates in .zap configuration file and re-open .zap file or just save this .zap file to apply the changes.%'
AND
SESSION_NOTICE.SESSION_REF = ?`,
sessionId
)
}

// exports
exports.getAllSessions = getAllSessions
exports.reloadSession = reloadSession
Expand Down Expand Up @@ -851,3 +877,5 @@ exports.getAllSessionPartitionInfoForSession =
getAllSessionPartitionInfoForSession
exports.selectDeviceTypePackageInfoFromDeviceTypeId =
selectDeviceTypePackageInfoFromDeviceTypeId
exports.deleteSessionNotificationsForDuplicateEndpointTypeMetaData =
deleteSessionNotificationsForDuplicateEndpointTypeMetaData
4 changes: 4 additions & 0 deletions src-electron/importexport/export.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ async function exportDataIntoFile(

await fsp.writeFile(filePath, JSON.stringify(state, null, 2))
await querySession.setSessionClean(db, sessionId)
await querySession.deleteSessionNotificationsForDuplicateEndpointTypeMetaData(
db,
sessionId
)
return filePath
}

Expand Down
218 changes: 181 additions & 37 deletions src-electron/importexport/import-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,17 @@ function sortEndpoints(endpoints) {
* @param {*} allZclPackageIds
* @param {*} endpointTypeId
* @param {*} clusters
* @param {*} endpointId
* @param {*} sessionId
*/
async function importClusters(db, allZclPackageIds, endpointTypeId, clusters) {
async function importClusters(
db,
allZclPackageIds,
endpointTypeId,
clusters,
endpointId,
sessionId
) {
let relevantZclPackageIds = allZclPackageIds
// Get all custom xml packages since they will be relevant packages as well.
let packageInfo = await queryPackage.getPackagesByPackageIds(
Expand Down Expand Up @@ -450,25 +459,31 @@ async function importClusters(db, allZclPackageIds, endpointTypeId, clusters) {
await importCommands(
db,
relevantZclPackageIds,
endpointTypeId,
endpointClusterId,
clusters[k].commands
clusters[k].commands,
clusters[k],
endpointId,
sessionId
)

await importAttributes(
db,
relevantZclPackageIds,
endpointTypeId,
endpointClusterId,
clusters[k].attributes,
clusters[k]
clusters[k],
endpointId,
sessionId
)

await importEvents(
db,
relevantZclPackageIds,
endpointClusterId,
clusters[k].events
clusters[k].events,
clusters[k],
endpointId,
sessionId
)
}
}
Expand All @@ -478,26 +493,66 @@ async function importClusters(db, allZclPackageIds, endpointTypeId, clusters) {
* Imports the list of commands from a cluster
* @param {*} db
* @param {*} allZclPackageIds
* @param {*} endpointTypeId
* @param {*} endpointClusterId
* @param {*} commands
* @param {*} cluster
* @param {*} endpointId
* @param {*} sessionId
*/
async function importCommands(
db,
allZclPackageIds,
endpointTypeId,
endpointClusterId,
commands
commands,
cluster,
endpointId,
sessionId
) {
if (commands) {
for (let l = 0; l < commands.length; l++) {
await queryImpexp.importCommandForEndpointType(
db,
allZclPackageIds,
endpointTypeId,
endpointClusterId,
commands[l]
)
for (const command of commands) {
try {
await queryImpexp.importCommandForEndpointType(
db,
allZclPackageIds,
endpointClusterId,
command
)
} catch (err) {
if (err.code === 'SQLITE_CONSTRAINT') {
querySessionNotice.setNotification(
db,
'WARNING',
"Duplicate endpoint type command '" +
command.name +
"' for " +
cluster.name +
' cluster on endpoint ' +
endpointId +
'. Remove duplicates in .zap configuration file and re-open .zap file' +
' or just save this .zap file to apply the changes.',
sessionId,
1,
0
)
env.logWarning(
"Duplicate endpoint type command '" +
command.name +
"' for " +
cluster.name +
' cluster on endpoint ' +
endpointId +
'. Remove duplicates in .zap configuration file and re-open .zap file' +
' or just save this .zap file to apply the changes.'
)
} else {
// Handle other errors
env.logError(
'Unexpected error when inserting into endpoint type command table:',
err.message
)
throw err
}
}
}
}
}
Expand All @@ -506,28 +561,67 @@ async function importCommands(
* Imports the list of attributes from a cluster
* @param {*} db
* @param {*} allZclPackageIds
* @param {*} endpointTypeId
* @param {*} endpointClusterId
* @param {*} attributes
* @param {*} cluster
* @param {*} endpointId
* @param {*} sessionId
*/
async function importAttributes(
db,
allZclPackageIds,
endpointTypeId,
endpointClusterId,
attributes,
cluster
cluster,
endpointId,
sessionId
) {
if (attributes) {
for (let m = 0; m < attributes.length; m++) {
await queryImpexp.importAttributeForEndpointType(
db,
allZclPackageIds,
endpointClusterId,
attributes[m],
cluster
)
for (const attribute of attributes) {
try {
await queryImpexp.importAttributeForEndpointType(
db,
allZclPackageIds,
endpointClusterId,
attribute,
cluster
)
} catch (err) {
if (err.code === 'SQLITE_CONSTRAINT') {
querySessionNotice.setNotification(
db,
'WARNING',
"Duplicate endpoint type attribute '" +
attribute.name +
"' for " +
cluster.name +
' cluster on endpoint ' +
endpointId +
'. Remove duplicates in .zap configuration file and re-open .zap file' +
' or just save this .zap file to apply the changes.',
sessionId,
1,
0
)
env.logWarning(
"Duplicate endpoint type attribute '" +
attribute.name +
"' for " +
cluster.name +
' cluster on endpoint ' +
endpointId +
'. Remove duplicates in .zap configuration file and re-open .zap file' +
' or just save this .zap file to apply the changes.'
)
} else {
// Handle other errors
env.logError(
'Unexpected error when inserting into endpoint type attribute table:',
err.message
)
throw err
}
}
}
}
}
Expand All @@ -538,16 +632,64 @@ async function importAttributes(
* @param {*} allZclPackageIds
* @param {*} endpointClusterId
* @param {*} events
* @param {*} cluster
* @param {*} endpointId
* @param {*} sessionId
*/
async function importEvents(db, allZclPackageIds, endpointClusterId, events) {
async function importEvents(
db,
allZclPackageIds,
endpointClusterId,
events,
cluster,
endpointId,
sessionId
) {
if (events) {
for (let n = 0; n < events.length; n++) {
await queryImpexp.importEventForEndpointType(
db,
allZclPackageIds,
endpointClusterId,
events[n]
)
for (const event of events) {
try {
await queryImpexp.importEventForEndpointType(
db,
allZclPackageIds,
endpointClusterId,
event
)
} catch (err) {
if (err.code === 'SQLITE_CONSTRAINT') {
querySessionNotice.setNotification(
db,
'WARNING',
"Duplicate endpoint type event '" +
event.name +
"' for " +
cluster.name +
' cluster on endpoint ' +
endpointId +
'. Remove duplicates in .zap configuration file and re-open .zap file' +
' or just save this .zap file to apply the changes.',
sessionId,
1,
0
)
env.logWarning(
"Duplicate endpoint type event '" +
event.name +
"' for " +
cluster.name +
' cluster on endpoint ' +
endpointId +
'. Remove duplicates in .zap configuration file and re-open .zap file' +
' or just save this .zap file to apply the changes.'
)
} else {
// Handle other errors
env.logError(
'Unexpected error when inserting into endpoint type event table:',
err.message
)
throw err
}
}
}
}
}
Expand Down Expand Up @@ -1393,7 +1535,9 @@ async function importEndpointTypes(
db,
allZclPackageIds,
endpointTypeId,
endpointTypes[i].clusters
endpointTypes[i].clusters,
endpointId,
sessionId
)

/**
Expand Down
Loading

0 comments on commit 8f98309

Please sign in to comment.