<https://cfml.slack.com/archives/C06TSRXCJ/p165471...
# box-products
b
https://cfml.slack.com/archives/C06TSRXCJ/p1654711078273519?thread_ts=1654677414.626059&amp;cid=C06TSRXCJ Forking this conversation since I believe the original poster is satisfied and I don't want to keep spamming them
In my case, I believe you are right, though the thread is sitting here rather than specifically on multiselect.cfc:298 https://github.com/Ortus-Solutions/commandbox/blob/development/src/cfml/system/Shell.cfc#L398
yeah... it did get there by way of https://github.com/Ortus-Solutions/commandbox/blob/development/src/cfml/system/services/ServerService.cfc#L341 so, as you suspected, it is waiting on an answer about what to do because it thinks the server is already running when it isn't
Since 'server stop' doesn't throw an error when you try to stop a server that isn't running (and because the nssm startup directory is the web root), updating the nssm command from
server start --console --debug
to
server stop && server start --console --debug
seems to be working so far. After that update, I've done the following multiple times and the server has been coming back up consistently the first time • manually stopped and started the service using the Windows service manager UI • manually restarted the service using the service manager UI • used stop-service and start-service PowerShell commands • used restart-service PowerShell commands • rebooted the server without stopping the service first (because the service is set to auto start delayed) • rebooted after stopping the service first I'm going to repeat those tests a few more times each before calling it a successful workaround (provided you can't think of any negative impact I'm not seeing yet, @bdw429s).
b
@bhartsfield That could work if the
server stop
command checks the status (which will inherently remove any invalid PID files), but you may as well just run a
server status
command in that case. I'm not actually aware of the stop command checking the status anywhere.
The "real" way to avoid the prompt is to force the CLI into non-interactive mode like I said. I haven't found any reliable way to detect that within CommandBox itself, which is why I'm just setting the env var.
Let me know if you don't know how to set env vars with NSSM.
The service manager module would already do this for you 🙂
b
I did try the noninteractivemode env var but it didnt make a difference for me.
b
Then you didn't do it right, lol
Or you're on an older version of CommandBox
b
yeah, from your last sentence, I just fae palmed
b
The first 5.5 release didn't check that setting, but the 5.5.2 release does.
b
... i set a dotenv env var, not an nssm environment var 😕
b
Um, a dotenv may work-- depends on when it's loaded 🤔
preServerStart
fires right before the "is running?" check and I think that's when dotenv loads, so in theory it should be there
b
meaning i used
dotenv set box_config_nonInteractiveShell true
but that didn't seem to make a difference
b
Did it get put into the
.env
file in the web root?
You didn't say where you ran that command
b
from the webroot of the target server instance (it ended up in the correct .env file)
b
It's also worth noting, if you put it in a
.env
file, that wold also apply when you do a normal
server start
which I wouldn't consider desirable.
Relegating it to the service means it only applies then
b
Sorry, are you saying it should go in the start command that NSSM is using?
b
not sure-- there is debugging you can enable in the dotenv module that will tell you what it loads and when. You'd have to debug it.
👍 1
Sorry, are you saying it should go in the start command that NSSM is using?
That's where it makes the most sense, since you really only want that flag set when specifically starting the server as a service
b
got it. ok... I'm caught up now 🙂
b
Copy code
nssm.exe set "my-service" AppEnvironmentExtra box_config_nonInteractiveShell=true
I should charge you to look at that though since it's from the Service Manager code 😉
b
ha
b
CLOSE YOUR EYES-- COMPANY SECRETS!!!
You can basically give NSSM one or more env vars and it will toss them into the environment where it starts the service
Handy for this sort of thing
b
well... in the spirit of fairness, even though I seem to have it working. I am still going to revisit the env var because it sounds like a more easily explained solution. I am also going to run back through this using the service manager instead of NSSM (because I definitely saw the same service/pid disconnect problem when I used it and went back to NSSM). I only have one service manager license. I used it on my local dev box I believe. Any issues with me removing it form there and using it on another server instead?
guessing not as long as its only being used on one server at a time
b
Yep, that's fine
b
ok thanks
b
Just make sure you install the latest version
Which actually has some new coolness added to it
You can now also use it to create services out of Task Runners
Copy code
task service create
b
nice! Now I just need to work some tasks into this new API so I can justify the service manager to my boss again 🙂
b
lol
I just build the task stuff this week (after wanting to do it for years) for a client project where we needed to spin up some Rabbit MQ consumer threads on a random windows server to run active directory commands.
I'm using the new RPC Server/client stuff I just built into the RabbitSDK so their docker/linux hosted app can still call out to our little micrservice running on WIndows that is tied to those native exe binaries for messing with their LDAP accounts
It just requires an RPC server running in my task runner which has a
while( true ) sleep( 1000 )
after it
Copy code
channel = rabbitClient
	.startRPCServer( 
		queue='RPC_requests',
		consumer=(method,args)=>{
			return "hello world";
		}
	);
And then our app sends it a requests via message queues
Copy code
result = rabbitClient.RPCClient( 'RPC_requests' ).sayHello();
❤️ 1
It's super lightweight and prevented us from needing to build out an entire HTTP/MVC/REST API just to host like 3 little calls
b
Good idea. I'm hoping to start firing some events off in this API and then create a new app to consume those for a (near) real-time dashboard
RMQ events*
b
Oh yeah, I love rabbit for that--especially with the built in websocket plugin
I have a number of task runner based daemons for this client (most of them running minibox docker on their swarm) that push real-time events to their dashboards all via Rabbit
🙌 1
b
my experience with it is still pretty limited but I've had fun with what little I've done with it so far
b
Curious what specifically you found limited
b
Not sure I follow... the only thing limited right now is my experience with it
b
I'm just trying to figure out what rabbit feature you were using
Ah, I see- you meant your experience was limited. Got it-- I thought you were saying it had limited features. 👍
👍 1
b
the basics. one queue setup and one app subscribed firing stuff into it. So I'm not sure what you are getting out of, for example, the websocket plugin you mentioned yet.
b
ok, I was just curious what
RMQ events*
meant, like if that was some special feature of rabbit I hadn't heard of
Or if you just meant the normal thing sending a message to a queue, etc, etc
b
oh gotcha. my terminology probably reflects my experience with it
b
The stomp plugin is nice because you just send a message to a queue and that message gets sent out to any subscribed websocket listeners.
And when a websocket publishes a message, it just goes into a queue as well
b
oh! Now I see what you mean!
nice
b
It takes some work to setup auth so it's not just all open to the world (like every sample chat app ever) but we already used JWT so it was fairly easy to piggy back off that with a custom HTTP-based auth service
SO each browser authenticates to stomp with thei JWT and then I know • who they are • what channels they can subscribe to
Then we have custom topics for each user so i can push a message to
user_notifications.bobby
and it pops up in only your browser (if you're online)
b
very, very cool
b
Or push to
admin_notification_dashboard
and all admin users with that dashboard open get the message
I even built a REST over STOMP plugin that allows you to remote-execute coldbox events over stomp as an alternative to Ajax as it re-uses existing established TCP connection instead of re-negatiating.
b
sounds like a good start to something like interactive live support directly in your app instead of over zoom, teams, etc...
Yeah, my client built their own basic "Slack" chat into their app
And tied it into Twillio so their agents can live message where the recipient is actually via text message
b
Turbotax has an interactive life support like that and I was blown away when I first saw it and trying to wrap my brain around how they managed it.
b
And it's all real-time
We've also converted a lot of their "every 5 minutes" sort of scheduled tasks that, say, look for a new incoming lead in the DB to just fire an async message right when the lead comes in and then a rabbit consumer running out in a Docker swarm task runner immediately processes it
b
another fantastic idea lol
b
I've thought about blogging some of it, but the issue is it all uses a fairly specific set of technologies that don't necessarily match everyone's stack so I don't know what the applicability is to the average dev who maybe has a slightly different stack
We also rely heavily on Couchbase for super-fast caching of data that's been handled by our real time processes to reduce DB traffic
👍 1
b
Where I would have probably ended up with about 4 microservices, you have one and some task runners
b
yeah, "microservice" originally to me was an "HTTP REST API", but with message queues, I've realized that doesn't have to be the case.
b
same
b
A super duper lightweight rabbit consumer thread (or 50 of them!) running off in a container in the swarm can also be a microservice
❤️ 1
b
and tons of times, that's all you'd need
Lots of good stuff to pile onto my tinker list. Thanks! I'm going to go do actual work now I guess.
👍 1
I've not been able to get the nonInteractiveShell option to stop the problem. I've set it through NSSM like you mentioned (and confirmed that its there when I edit the service). I also went into the webroot of the server and ran
config set nonInteractiveShell=true
(and confirmed it stuck with
config show
) no matter where I put it, it didn't stop the problem of the start hanging while waiting on input.
server status && server start ....
also didn't work as a replacement for
server stop && server start ...
it just got the whole thing caught in a loop as it filled up %commandbox_home%\.logs\server.out.log with these
Copy code
[ERROR] runwar.context: java.net.ConnectException: Connection refused: connect
[ERROR] runwar.context: at java.base/java.net.PlainSocketImpl.connect0(Native Method)
[ERROR] runwar.context: at java.base/java.net.PlainSocketImpl.socketConnect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.AbstractPlainSocketImpl.connect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.SocksSocketImpl.connect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.Socket.connect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.Socket.connect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.Socket.<init>(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.Socket.<init>(Unknown Source)
[ERROR] runwar.context: at runwar.Stop.stopServer(Stop.java:26)
[ERROR] runwar.context: at runwar.Server.startServer(Server.java:206)
[ERROR] runwar.context: at runwar.Start.main(Start.java:50)
[INFO ] runwar.context: Could not stop server.  Are you sure it is running, and listing for stop requests on port 49909?
[ERROR] runwar.context: java.net.ConnectException: Connection refused: connect
[ERROR] runwar.context: at java.base/java.net.PlainSocketImpl.connect0(Native Method)
[ERROR] runwar.context: at java.base/java.net.PlainSocketImpl.socketConnect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.AbstractPlainSocketImpl.connect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.SocksSocketImpl.connect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.Socket.connect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.Socket.connect(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.Socket.<init>(Unknown Source)
[ERROR] runwar.context: at java.base/java.net.Socket.<init>(Unknown Source)
[ERROR] runwar.context: at runwar.Stop.stopServer(Stop.java:26)
[ERROR] runwar.context: at runwar.Server.startServer(Server.java:206)
[ERROR] runwar.context: at runwar.Start.main(Start.java:50)
[INFO ] runwar.context: Could not stop server.  Are you sure it is running, and listing for stop requests on port 50025?
the
server stop && server start...
workaround is holding strong though
b
Hmm, that stack trace above is for a code path that would only be hit if you ran
server stop
so I'm not sure how it would possibly be running when you ran
server status
it didn't stop the problem of the start hanging while waiting on input.
And you • confirmed the thread was specifically running the mulitSelect code? • Are on CommandBox 5.5.2? It should really be impossible to hit that code path when non interactive shell is turned on.
Here's the check for that
Copy code
/**
	 * Is the current terminal interactive?
	 * @returns boolean
  	 **/
	function isTerminalInteractive() {
		// Check for config setting called "nonInteractiveShell"
		if( configService.settingExists( 'nonInteractiveShell' ) && isBoolean( configService.getSetting( "nonInteractiveShell" ) ) ) {
			return !configService.getSetting( "nonInteractiveShell" );
		// Next check for an Environment Variable called "CI" that is set
		} else if( systemSettings.getSystemSetting( 'CI', '__NOT_SET__' ) != '__NOT_SET__' ) {
			return false;
		// System.console() will return null is the stndin or stndout is not a TTY
		} else if( isNull( createObject( 'java', 'java.lang.System' ).console() ) ) {
			return false;
		// Default to true
		} else {
			return true;
		}
	}
That config setting trumps everything else
But again, it was added in the latest 5.5.2 update of CommandBox-- earlier versions of server start did not check if the shell was interactive or not before prompting the user
b
I believe it is 5.5.1. I will check in the morning and upgrade if it is then try again Yes, I confirmed the stack was still waiting on input from the multi select code.
b
If you're on 5.5.1 then that's for sure the issue
👍 1
b
yep... v5.5.1+00562
dang... no auto-upgrade between 5.5.1 and 5.5.2
I couldn't stand it... I upgraded and retested with JUST the env var (set through NSSM environment vars). Not only does that seem to have fixed the issue (as well), the server start up is actually much faster now.
I'll run a bunch more service stop/start/restart and reboot tests but I'm pretty confident the issue is gone.
...yes, I removed 'server stop &&' from the service start command 😉