back to listing index

proposal: gnatsd as embedded package for my Go services · Issue #106 · nats-io/gnatsd

[web search]
Original source (github.com)
Tags: examples golang go windows system-service
Clipped on: 2018-08-13
Find file Copy path
/
/
service_windows.go
122 lines (106 sloc)
3.29 KB
1
//
Copyright 2012-2018 The NATS Authors
2
//
Licensed under the Apache License, Version 2.0 (the "License");
3
//
you may not use this file except in compliance with the License.
4
//
You may obtain a copy of the License at
5
//
6
//
http://www.apache.org/licenses/LICENSE-2.0
7
//
8
//
Unless required by applicable law or agreed to in writing, software
9
//
distributed under the License is distributed on an "AS IS" BASIS,
10
//
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
//
See the License for the specific language governing permissions and
12
//
limitations under the License.
13
14
package
server
15
16
import
(
17
"
os
"
18
"
time
"
19
20
"
golang.org/x/sys/windows/svc
"
21
"
golang.org/x/sys/windows/svc/debug
"
22 )
23
24
const
(
25 serviceName =
"
gnatsd
"
26 reopenLogCode =
128
27 reopenLogCmd = svc.
Cmd
(reopenLogCode)
28 acceptReopenLog = svc.
Accepted
(reopenLogCode)
29 )
30
31
//
winServiceWrapper implements the svc.Handler interface for implementing
32
//
gnatsd as a Windows service.
33
type
winServiceWrapper
struct
{
34 server *Server
35 }
36
37
var
dockerized
=
false
38
39
func
init
() {
40
if
v
,
exists
:=
os.
LookupEnv
(
"
NATS_DOCKERIZED
"
); exists && v ==
"
1
"
{
41 dockerized =
true
42 }
43 }
44
45
//
Execute will be called by the package code at the start of
46
//
the service, and the service will exit once Execute completes.
47
//
Inside Execute you must read service change requests from r and
48
//
act accordingly. You must keep service control manager up to date
49
//
about state of your service by writing into s as required.
50
//
args contains service name followed by argument strings passed
51
//
to the service.
52
//
You can provide service exit code in exitCode return parameter,
53
//
with 0 being "no error". You can also indicate if exit code,
54
//
if any, is service specific or not by using svcSpecificEC
55
//
parameter.
56
func
(
w
*
winServiceWrapper
)
Execute
(args []string, changes <-chan svc.ChangeRequest,
57 status chan<- svc.Status) (bool, uint32) {
58
59 status
<-
svc.
Status
{State: svc.
StartPending
}
60
go
w.
server
.
Start
()
61
62
//
Wait for accept loop(s) to be started
63
if
!w.
server
.
ReadyForConnections
(
10
* time.
Second
) {
64
//
Failed to start.
65
return
false
,
1
66 }
67
68 status
<-
svc.
Status
{
69 State: svc.
Running
,
70 Accepts: svc.
AcceptStop
| svc.
AcceptShutdown
| svc.
AcceptParamChange
| acceptReopenLog,
71 }
72
73 loop:
74
for
change
:=
range
changes {
75
switch
change.
Cmd
{
76
case
svc.
Interrogate
:
77 status
<-
change.
CurrentStatus
78
case
svc.
Stop
, svc.
Shutdown
:
79 w.
server
.
Shutdown
()
80
break
loop
81
case
reopenLogCmd:
82
//
File log re-open for rotating file logs.
83 w.
server
.
ReOpenLogFile
()
84
case
svc.
ParamChange
:
85
if
err
:=
w.
server
.
Reload
(); err !=
nil
{
86 w.
server
.
Errorf
(
"
Failed to reload server configuration:
%s
"
, err)
87 }
88
default
:
89 w.
server
.
Debugf
(
"
Unexpected control request:
%v
"
, change.
Cmd
)
90 }
91 }
92
93 status
<-
svc.
Status
{State: svc.
StopPending
}
94
return
false
,
0
95 }
96
97
//
Run starts the NATS server as a Windows service.
98
func
Run
(
server
*
Server
)
error
{
99
if
dockerized {
100 server.
Start
()
101
return
nil
102 }
103
run
:=
svc.
Run
104
isInteractive
,
err
:=
svc.
IsAnInteractiveSession
()
105
if
err !=
nil
{
106
return
err
107 }
108
if
isInteractive {
109 run = debug.
Run
110 }
111
return
run
(serviceName, &winServiceWrapper{server})
112 }
113
114
//
isWindowsService indicates if NATS is running as a Windows service.
115
func
isWindowsService
()
bool
{
116
if
dockerized {
117
return
false
118 }
119
isInteractive
,
_
:=
svc.
IsAnInteractiveSession
()
120
return
!isInteractive
121 }
Press h to open a hovercard with more details.