@@ -23,16 +23,65 @@ import (
23
23
"os"
24
24
"os/exec"
25
25
"os/signal"
26
+ "strconv"
26
27
"strings"
28
+ "time"
27
29
30
+ "github.com/ibm-messaging/mq-container/internal/ready"
28
31
"github.com/ibm-messaging/mq-container/pkg/name"
29
32
)
30
33
31
34
func queueManagerStarted (ctx context.Context ) (bool , error ) {
35
+
32
36
name , err := name .GetQueueManagerName ()
33
37
if err != nil {
34
38
return false , err
35
39
}
40
+
41
+ readyStrings := []string {
42
+ "(RUNNING)" ,
43
+ "(RUNNING AS STANDBY)" ,
44
+ "(RECOVERY GROUP LEADER)" ,
45
+ "(STARTING)" ,
46
+ "(REPLICA)" ,
47
+ }
48
+
49
+ // For Native-HA only, check if the queue manager instance is in-sync with one or more replicas
50
+ // - If not in-sync within the expected time period, revert to checking on queue manager 'ready' status
51
+ // - This ensures we do not block indefinitely for breaking changes (i.e. protocol changes)
52
+ if os .Getenv ("MQ_NATIVE_HA" ) == "true" {
53
+
54
+ // Check if the Native-HA queue manager instance is currently in-sync
55
+ isReadyToSync , isInSync , err := isInSyncWithReplicas (ctx , name , readyStrings )
56
+ if err != nil {
57
+ return false , err
58
+ } else if isInSync {
59
+ return true , nil
60
+ }
61
+
62
+ // Check if the Native-HA queue manager instance is ready-to-sync
63
+ // - A successful queue manager 'ready' status indicates that we are ready-to-sync
64
+ if ! isReadyToSync {
65
+ return false , nil
66
+ }
67
+ err = ready .SetReadyToSync ()
68
+ if err != nil {
69
+ return false , err
70
+ }
71
+
72
+ // Check if the time period for checking in-sync has now expired
73
+ // - We have already confirmed a successful queue manager 'ready' status
74
+ // - Therefore the expiration of the in-sync time period will result in success
75
+ expired , err := hasInSyncTimePeriodExpired ()
76
+ if err != nil {
77
+ return false , err
78
+ } else if expired {
79
+ return true , nil
80
+ }
81
+
82
+ return false , nil
83
+ }
84
+
36
85
// Specify the queue manager name, just in case someone's created a second queue manager
37
86
// #nosec G204
38
87
cmd := exec .CommandContext (ctx , "dspmq" , "-n" , "-m" , name )
@@ -42,18 +91,60 @@ func queueManagerStarted(ctx context.Context) (bool, error) {
42
91
fmt .Println (err )
43
92
return false , err
44
93
}
45
- readyStrings := []string {
46
- "(RUNNING)" ,
47
- "(RUNNING AS STANDBY)" ,
48
- "(RECOVERY GROUP LEADER)" ,
49
- "(STARTING)" ,
50
- "(REPLICA)" ,
51
- }
94
+
52
95
for _ , checkString := range readyStrings {
53
96
if strings .Contains (string (out ), checkString ) {
54
97
return true , nil
55
98
}
56
99
}
100
+
101
+ return false , nil
102
+ }
103
+
104
+ // isInSyncWithReplicas returns the in-sync status for a Native-HA queue manager instance
105
+ func isInSyncWithReplicas (ctx context.Context , name string , readyStrings []string ) (bool , bool , error ) {
106
+
107
+ cmd := exec .CommandContext (ctx , "dspmq" , "-n" , "-o" , "nativeha" , "-m" , name )
108
+ out , err := cmd .CombinedOutput ()
109
+ if err != nil {
110
+ return false , false , err
111
+ } else if strings .Contains (string (out ), "INSYNC(YES)" ) {
112
+ return true , true , nil
113
+ }
114
+
115
+ for _ , checkString := range readyStrings {
116
+ if strings .Contains (string (out ), checkString ) {
117
+ return true , false , nil
118
+ }
119
+ }
120
+
121
+ return false , false , nil
122
+ }
123
+
124
+ // hasInSyncTimePeriodExpired returns true if a Native-HA queue manager instance is not in-sync within the expected time period, otherwise false
125
+ func hasInSyncTimePeriodExpired () (bool , error ) {
126
+
127
+ // Default timeout 5 seconds
128
+ var timeout int64 = 5
129
+ var err error
130
+
131
+ // Check if a timeout override has been set
132
+ customTimeout := os .Getenv ("MQ_NATIVE_HA_IN_SYNC_TIMEOUT" )
133
+ if customTimeout != "" {
134
+ timeout , err = strconv .ParseInt (customTimeout , 10 , 64 )
135
+ if err != nil {
136
+ return false , err
137
+ }
138
+ }
139
+
140
+ isReadyToSync , readyToSyncStartTime , err := ready .GetReadyToSyncStartTime ()
141
+ if err != nil {
142
+ return false , err
143
+ }
144
+ if isReadyToSync && time .Now ().Unix ()- readyToSyncStartTime .Unix () >= timeout {
145
+ return true , nil
146
+ }
147
+
57
148
return false , nil
58
149
}
59
150
0 commit comments