Skip to content

Commit

Permalink
Clean up server-mode for concurrent use (#598)
Browse files Browse the repository at this point in the history
* Share the ipc socket same way as single-instance shares sockets.

* Some code cleanup.

* Increase feature level to trigger IDE tests.

* Make server load both zigbee and matter data.

* Fix the hang of the generation in the client/server case.
  • Loading branch information
tecimovic authored Jul 13, 2022
1 parent 7f73d2c commit 0fe96a7
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 56 deletions.
2 changes: 1 addition & 1 deletion apack.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Graphical configuration tool for application and libraries based on Zigbee Cluster Library.",
"path": [".", "node_modules/.bin/", "ZAP.app/Contents/MacOS"],
"requiredFeatureLevel": "apack.core:9",
"featureLevel": 75,
"featureLevel": 76,
"uc.triggerExtension": "zap",
"executable": {
"zap:win32.x86_64": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
"zaphelp": "node src-script/zap-start.js --help",
"zap-dotdot": "node src-script/zap-start.js --logToStdout --zcl ./zcl-builtin/dotdot/library.xml",
"zap-devserver": "node src-script/zap-start.js server --allowCors --logToStdout --gen ./test/gen-template/zigbee/gen-templates.json --reuseZapInstance",
"server": "node src-script/zap-start.js server --logToStdout --gen ./test/gen-template/zigbee/gen-templates.json --reuseZapInstance",
"server": "node src-script/zap-start.js server --logToStdout --zcl ./zcl-builtin/silabs/zcl.json --zcl ./zcl-builtin/matter/zcl.json --gen ./test/gen-template/zigbee/gen-templates.json --reuseZapInstance",
"stop": "node src-script/zap-start.js stop --reuseZapInstance",
"status": "node src-script/zap-start.js status --reuseZapInstance",
"self-check": "node src-script/zap-start.js selfCheck -g ./test/gen-template/zigbee/gen-templates.json",
Expand Down
14 changes: 5 additions & 9 deletions src-electron/main-process/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,16 @@ env.versionsCheck()
env.setProductionEnv()

let argv = args.processCommandLineArguments(process.argv)

util.mainOrSecondaryInstance(
argv.reuseZapInstance,
() => {
startup.startUpMainInstance(
{
quitFunction: null,
uiEnableFunction: null,
},
argv
)
startup.startUpMainInstance(argv, {
quitFunction: () => process.exit(0),
uiEnableFunction: null,
})
},
() => {
startup.startUpSecondaryInstance(null, argv)
startup.startUpSecondaryInstance(argv, { quitFunction: null })
}
)

Expand Down
60 changes: 26 additions & 34 deletions src-electron/main-process/startup.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,35 +323,28 @@ async function startServer(argv, quitFunction) {
}
})
mainDatabase = db

await zclLoader.loadZclMetafiles(db, argv.zclProperties)
return generatorEngine
.loadTemplates(db, argv.generationTemplate)
.then((ctx) => {
if (ctx.error) {
env.logWarning(ctx.error)
try {
await zclLoader.loadZclMetafiles(db, argv.zclProperties)
let ctx = await generatorEngine.loadTemplates(db, argv.generationTemplate)
if (ctx.error) {
env.logWarning(ctx.error)
}
await httpServer.initHttpServer(
ctx.db,
argv.httpPort,
argv.studioHttpPort,
{
zcl: argv.zclProperties,
template: argv.generationTemplate,
allowCors: argv.allowCors,
}
return ctx
})
.then((ctx) => {
return httpServer
.initHttpServer(ctx.db, argv.httpPort, argv.studioHttpPort, {
zcl: argv.zclProperties,
template: argv.generationTemplate,
allowCors: argv.allowCors,
})
.then(() => {
ipcServer.initServer(ctx.db, argv.httpPort)
})
.then(() => ctx)
})
.then((ctx) => {
logRemoteData(httpServer.httpServerStartupMessage())
})
.catch((err) => {
env.logError(err)
throw err
})
)
await ipcServer.initServer(ctx.db, argv.httpPort)
logRemoteData(httpServer.httpServerStartupMessage())
} catch (err) {
env.logError(err)
throw err
}
}

/**
Expand Down Expand Up @@ -554,12 +547,12 @@ function logRemoteData(data) {
*
* @param {*} argv
*/
function startUpSecondaryInstance(quitFunction, argv) {
function startUpSecondaryInstance(argv, callbacks) {
console.log('🧐 Existing instance of zap will service this request.')
ipcClient.initAndConnectClient().then(() => {
ipcClient.on(ipcServer.eventType.overAndOut, (data) => {
logRemoteData(data)
if (quitFunction != null) quitFunction()
if (callbacks.quitFunction != null) callbacks.quitFunction()
else process.exit(0)
})

Expand Down Expand Up @@ -598,7 +591,7 @@ function quit() {
* @param {*} quitFunction
* @param {*} argv
*/
async function startUpMainInstance(callbacks, argv) {
async function startUpMainInstance(argv, callbacks) {
let quitFunction = callbacks.quitFunction
let uiFunction = callbacks.uiEnableFunction
if (quitFunction != null) {
Expand Down Expand Up @@ -671,7 +664,7 @@ async function startUpMainInstance(callbacks, argv) {
})
} else {
// If we run with node only, we force no UI as it won't work.
if (quitFunction == null) {
if (uiEnableFunction == null) {
argv.noUi = true
argv.showUrl = true
argv.standalone = false
Expand All @@ -681,11 +674,10 @@ async function startUpMainInstance(callbacks, argv) {
let uiEnabled = !argv.noUi
let zapFiles = argv.zapFiles
let port = await startNormal(quitFunction, argv)
let showUrl = argv.showUrl
if (uiEnabled && uiFunction != null) {
uiFunction(port, zapFiles, argv.uiMode, argv.standalone)
} else {
if (showUrl) {
if (argv.showUrl) {
// NOTE: this is parsed/used by Studio as the default landing page.
logRemoteData(httpServer.httpServerStartupMessage())
}
Expand Down
7 changes: 6 additions & 1 deletion src-electron/server/ipc-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ipc from 'node-ipc'
import * as env from '../util/env'
import * as ipcTypes from '../../src-shared/types/ipc-types'
const path = require('path')
const os = require('os')
const util = require('../util/util.js')
const watchdog = require('../main-process/watchdog')
const httpServer = require('../server/http-server.js')
Expand Down Expand Up @@ -47,7 +48,11 @@ const server: ipcTypes.Server = {
* Returns the socket path for the IPC.
*/
function socketPath() {
return path.join(env.appDirectory(), 'main.ipc')
var defaultSocketPath =
process.platform == 'win32'
? '\\\\.\\pipe\\' + 'zap-ipc' + '-sock'
: path.join(os.tmpdir(), 'zap-ipc' + '.sock')
return defaultSocketPath
}

function log(msg: string) {
Expand Down
21 changes: 11 additions & 10 deletions src-electron/ui/main-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
* limitations under the License.
*/

const { app } = require('electron')

// enable stack trace to be mapped back to the correct line number in TypeScript source files.
require('source-map-support').install()

const { app } = require('electron')

import * as args from '../util/args'
const env = require('../util/env')
const windowJs = require('./window')
Expand All @@ -31,7 +31,11 @@ env.versionsCheck()
env.setProductionEnv()

function hookSecondInstanceEvents(argv: args.Arguments) {
app.whenReady().then(() => startup.startUpSecondaryInstance(app.quit, argv))
app
.whenReady()
.then(() =>
startup.startUpSecondaryInstance(argv, { quitFunction: app.quit })
)
}

/**
Expand All @@ -41,13 +45,10 @@ function hookMainInstanceEvents(argv: args.Arguments) {
app
.whenReady()
.then(() =>
startup.startUpMainInstance(
{
quitFunction: app.quit,
uiEnableFunction: uiUtil.enableUi,
},
argv
)
startup.startUpMainInstance(argv, {
quitFunction: app.quit,
uiEnableFunction: uiUtil.enableUi,
})
)
.catch((err) => {
console.log(err)
Expand Down

0 comments on commit 0fe96a7

Please sign in to comment.