@@ -126,6 +126,11 @@ const localConfig =
126126
127127 // callback to main server to save the updated server config
128128 saveServerConfigFunc : null ,
129+ // startup extension check for readiness interval
130+ StartupIntervalHandle : null ,
131+ StartupInterval : 200 ,
132+ StartupMaxTime : 100 , //give extension 10seconds (StartupInterval*StartupMaxTime) to startup
133+ StartupMaxTimeCounter : 0 ,
129134}
130135const triggersandactions =
131136{
@@ -240,6 +245,48 @@ const triggersandactions =
240245 }
241246 ] ,
242247}
248+
249+
250+ // check for extension status so we can send a message out when all have reported read
251+ /**
252+ * checks for extensions sending 'ready' message and send out a 'StreamRollerReady' when all extensions have responded
253+ */
254+ function extensionReadinessCheckScheduler ( )
255+ {
256+ clearTimeout ( localConfig . StartupIntervalHandle )
257+ localConfig . StartupIntervalHandle = setInterval ( ( ) =>
258+ {
259+ extensionReadinessCheck ( )
260+ } , localConfig . StartupInterval ) ;
261+ }
262+ /**
263+ * Extension readiness check
264+ */
265+ function extensionReadinessCheck ( )
266+ {
267+ let AllExtensionsReady = true ; // negative check
268+ for ( var key in localConfig . extensions )
269+ {
270+ if ( localConfig . extensions [ key ] . state != "ready" )
271+ AllExtensionsReady = false ;
272+ }
273+ //are we out of time or extensions finished loading
274+ if ( localConfig . StartupMaxTimeCounter ++ > localConfig . StartupMaxTime
275+ || ( AllExtensionsReady && localConfig . extensions != { } && localConfig . server_socket != null ) )
276+ {
277+ // list extensions that failed to load in time
278+ if ( localConfig . StartupMaxTimeCounter ++ > localConfig . StartupMaxTime )
279+ {
280+ for ( var ext in localConfig . extensions )
281+ {
282+ if ( localConfig . extensions [ ext ] . state != "ready" )
283+ console . log ( `server startup time out for ${ ext } ` )
284+ }
285+ }
286+ mh . broadcastMessage ( localConfig . server_socket , sr_api . ServerPacket ( "StreamRollerReady" , localConfig . extensionname , { } ) )
287+ clearInterval ( localConfig . StartupIntervalHandle )
288+ }
289+ }
243290// ============================================================================
244291// FUNCTION: start
245292// ============================================================================
@@ -268,7 +315,15 @@ function start (app, server, exts, serverConfig, saveServerConfigFunc)
268315 // create our extension array
269316 exts . forEach ( ( elem , i ) =>
270317 {
271- localConfig . extensions [ elem ] = { } ;
318+ // extensions without backend servers may not send a running message via the socket
319+ // and will set it via a function callback from the init function.
320+ // That will happen before we get here so we need to make sure we don't overwrite
321+ // the running flags for these extensions
322+ if ( ! localConfig . extensions [ elem ] )
323+ {
324+ localConfig . extensions [ elem ] = { }
325+ localConfig . extensions [ elem ] . state = "loading" ;
326+ }
272327 } ) ;
273328 localConfig . backend_server = server ;
274329 cm . initcrypto ( ) ;
@@ -317,6 +372,7 @@ function onConnect (socket)
317372{
318373 socket . emit ( "connected" , socket . id ) ;
319374 socket . join ( localConfig . channel ) ;
375+ extensionReadinessCheckScheduler ( ) ;
320376 sendAddressTrigger ( ) ;
321377}
322378// ============================================================================
@@ -373,9 +429,14 @@ function onMessage (socket, server_packet)
373429 mh . errorMessage ( socket , "Missing type/from field" , server_packet ) ;
374430 return ;
375431 }
376- // add this socket to the extension if it doesn't already exist
432+ // add this socket to the extension list if it doesn't already exist
433+ // these will be extension not started by the server
377434 if ( typeof ( localConfig . extensions [ server_packet . from ] ) === "undefined" || ! localConfig . extensions [ server_packet . from ] )
435+ {
378436 localConfig . extensions [ server_packet . from ] = { } ;
437+ // added new extension so restart the check
438+ extensionReadinessCheckScheduler ( ) ;
439+ }
379440 // check we have a valid socket for this extension, don't need to check if the extension exists as it will have been added above
380441 if ( typeof ( localConfig . extensions [ server_packet . from ] . socket ) === "undefined" || ! localConfig . extensions [ server_packet . from ] . socket )
381442 {
@@ -388,7 +449,7 @@ function onMessage (socket, server_packet)
388449 else
389450 {
390451 // note that we currently only have one slot per connection. this works for extensions that are only loaded once
391- // but for webpage stuff we will need to allow more than one sockect for that extension name
452+ // but for webpage stuff we will need to allow more than one socket for that extension name
392453 // we need to append the socket id to the extension name to fix this!!!
393454 if ( localConfig . extensions [ server_packet . from ] . socket . id != socket . id )
394455 {
@@ -403,7 +464,11 @@ function onMessage (socket, server_packet)
403464 localConfig . connected_extensionlist [ server_packet . from ] = localConfig . extensions [ server_packet . from ] . socket . connected
404465 }
405466 // process the clients request
406- if ( server_packet . type === "RequestSoftwareVersion" )
467+ if ( server_packet . type === "ExtensionConnected" )
468+ localConfig . extensions [ server_packet . from ] = { state : "connected" } ;
469+ else if ( server_packet . type === "ExtensionReady" )
470+ localConfig . extensions [ server_packet . from ] = { state : "ready" } ;
471+ else if ( server_packet . type === "RequestSoftwareVersion" )
407472 mh . sendSoftwareVersion ( socket , server_packet . from ) ;
408473 else if ( server_packet . type === "RequestConfig" )
409474 mh . sendConfig ( socket , server_packet . from ) ;
@@ -771,7 +836,7 @@ function dataMonitorScheduler ()
771836// FUNCTION: sendAddressTrigger
772837// ============================================================================
773838/**
774- * Finds the trigger using the passed messagetype
839+ * sends "trigger_StreamRollerIPChanged" message
775840 * @returns trigger
776841 */
777842function sendAddressTrigger ( )
@@ -815,7 +880,7 @@ function findTriggerByMessageType (messagetype)
815880 for ( let i = 0 ; i < triggersandactions . triggers . length ; i ++ )
816881 {
817882 if ( triggersandactions . triggers [ i ] . messagetype . toLowerCase ( ) == messagetype . toLowerCase ( ) )
818- return triggersandactions . triggers [ i ] ;
883+ return structuredClone ( triggersandactions . triggers [ i ] ) ;
819884 }
820885 logger . err ( localConfig . SYSTEM_LOGGING_TAG + localConfig . extensionname +
821886 ".findTriggerByMessageType" , "failed to find trigger" , messagetype ) ;
@@ -845,8 +910,21 @@ function sendTrigger (data)
845910 )
846911 ) ;
847912}
913+ /**
914+ * Used by locally started extensions that have client webpages with the socket connection
915+ * these might not always be loading in a browser so we fake the ready flag on startup.
916+ * @param {string } ext
917+ */
918+ function readyMessage ( ext )
919+ {
920+ if ( ! localConfig . extensions [ ext ] )
921+ {
922+ localConfig . extensions [ ext ] = { }
923+ localConfig . extensions [ ext ] . state = "ready"
924+ }
925+ }
848926// ============================================================================
849927// EXPORTS:
850928// ============================================================================
851- export { start , triggersandactions } ;
929+ export { start , triggersandactions , readyMessage } ;
852930
0 commit comments