@@ -24,7 +24,7 @@ import (
24
24
25
25
const flagGRPCAddress = "grpc.address"
26
26
27
- type multiplexer struct {
27
+ type Multiplexer struct {
28
28
mu sync.Mutex
29
29
30
30
currentHeight , lastHeight int64
@@ -39,7 +39,7 @@ type multiplexer struct {
39
39
40
40
// NewMultiplexer creates a new ABCI wrapper for multiplexing
41
41
func NewMultiplexer (latestApp servertypes.ABCI , versions Versions , v * viper.Viper , home string ) (abci.Application , error ) {
42
- wrapper := & multiplexer {
42
+ wrapper := & Multiplexer {
43
43
latestApp : latestApp ,
44
44
versions : versions ,
45
45
}
@@ -101,7 +101,7 @@ func NewMultiplexer(latestApp servertypes.ABCI, versions Versions, v *viper.Vipe
101
101
return wrapper , nil
102
102
}
103
103
104
- func (m * multiplexer ) getLatestHeight (rootDir string , v * viper.Viper ) (int64 , error ) {
104
+ func (m * Multiplexer ) getLatestHeight (rootDir string , v * viper.Viper ) (int64 , error ) {
105
105
dataDir := filepath .Join (rootDir , "data" )
106
106
db , err := dbm .NewDB ("application" , server .GetAppDBBackend (v ), dataDir )
107
107
if err != nil {
@@ -114,7 +114,7 @@ func (m *multiplexer) getLatestHeight(rootDir string, v *viper.Viper) (int64, er
114
114
}
115
115
116
116
// getAppForHeight gets the appropriate app based on height
117
- func (m * multiplexer ) getAppForHeight (height int64 ) (servertypes.ABCI , error ) {
117
+ func (m * Multiplexer ) getAppForHeight (height int64 ) (servertypes.ABCI , error ) {
118
118
m .mu .Lock ()
119
119
defer m .mu .Unlock ()
120
120
@@ -179,31 +179,59 @@ func (m *multiplexer) getAppForHeight(height int64) (servertypes.ABCI, error) {
179
179
return NewRemoteABCIClient (m .conn ), nil
180
180
}
181
181
182
- func (m * multiplexer ) ApplySnapshotChunk (_ context.Context , req * abci.RequestApplySnapshotChunk ) (* abci.ResponseApplySnapshotChunk , error ) {
182
+ // Cleanup allows proper multiplexer termination.
183
+ func (m * Multiplexer ) Cleanup () error {
184
+ m .mu .Lock ()
185
+ defer m .mu .Unlock ()
186
+
187
+ var errs error
188
+
189
+ // stop any running app
190
+ if m .activeVersion .Appd != nil && m .activeVersion .Appd .Pid () != appd .AppdStopped {
191
+ log .Printf ("Stopping app for height %d" , m .activeVersion .UntilHeight )
192
+ if err := m .activeVersion .Appd .Stop (); err != nil {
193
+ errs = errors .Join (errs , fmt .Errorf ("failed to stop app for height %d: %w" , m .activeVersion .UntilHeight , err ))
194
+ }
195
+ m .started = false
196
+ m .activeVersion = Version {}
197
+ }
198
+
199
+ // close gRPC connection
200
+ if m .conn != nil {
201
+ if err := m .conn .Close (); err != nil {
202
+ errs = errors .Join (errs , fmt .Errorf ("failed to close gRPC connection: %w" , err ))
203
+ }
204
+ m .conn = nil
205
+ }
206
+
207
+ return errs
208
+ }
209
+
210
+ func (m * Multiplexer ) ApplySnapshotChunk (_ context.Context , req * abci.RequestApplySnapshotChunk ) (* abci.ResponseApplySnapshotChunk , error ) {
183
211
app , err := m .getAppForHeight (m .lastHeight )
184
212
if err != nil {
185
213
return nil , fmt .Errorf ("failed to get app for height %d: %w" , m .lastHeight , err )
186
214
}
187
215
return app .ApplySnapshotChunk (req )
188
216
}
189
217
190
- func (m * multiplexer ) CheckTx (_ context.Context , req * abci.RequestCheckTx ) (* abci.ResponseCheckTx , error ) {
218
+ func (m * Multiplexer ) CheckTx (_ context.Context , req * abci.RequestCheckTx ) (* abci.ResponseCheckTx , error ) {
191
219
app , err := m .getAppForHeight (m .lastHeight )
192
220
if err != nil {
193
221
return nil , fmt .Errorf ("failed to get app for height %d: %w" , m .lastHeight , err )
194
222
}
195
223
return app .CheckTx (req )
196
224
}
197
225
198
- func (m * multiplexer ) Commit (context.Context , * abci.RequestCommit ) (* abci.ResponseCommit , error ) {
226
+ func (m * Multiplexer ) Commit (context.Context , * abci.RequestCommit ) (* abci.ResponseCommit , error ) {
199
227
app , err := m .getAppForHeight (m .lastHeight )
200
228
if err != nil {
201
229
return nil , fmt .Errorf ("failed to get app for height %d: %w" , m .lastHeight , err )
202
230
}
203
231
return app .Commit ()
204
232
}
205
233
206
- func (m * multiplexer ) ExtendVote (ctx context.Context , req * abci.RequestExtendVote ) (* abci.ResponseExtendVote , error ) {
234
+ func (m * Multiplexer ) ExtendVote (ctx context.Context , req * abci.RequestExtendVote ) (* abci.ResponseExtendVote , error ) {
207
235
m .lastHeight = req .Height
208
236
app , err := m .getAppForHeight (req .Height )
209
237
if err != nil {
@@ -212,7 +240,7 @@ func (m *multiplexer) ExtendVote(ctx context.Context, req *abci.RequestExtendVot
212
240
return app .ExtendVote (ctx , req )
213
241
}
214
242
215
- func (m * multiplexer ) FinalizeBlock (_ context.Context , req * abci.RequestFinalizeBlock ) (* abci.ResponseFinalizeBlock , error ) {
243
+ func (m * Multiplexer ) FinalizeBlock (_ context.Context , req * abci.RequestFinalizeBlock ) (* abci.ResponseFinalizeBlock , error ) {
216
244
m .lastHeight = req .Height
217
245
app , err := m .getAppForHeight (req .Height )
218
246
if err != nil {
@@ -221,43 +249,43 @@ func (m *multiplexer) FinalizeBlock(_ context.Context, req *abci.RequestFinalize
221
249
return app .FinalizeBlock (req )
222
250
}
223
251
224
- func (m * multiplexer ) Info (_ context.Context , req * abci.RequestInfo ) (* abci.ResponseInfo , error ) {
252
+ func (m * Multiplexer ) Info (_ context.Context , req * abci.RequestInfo ) (* abci.ResponseInfo , error ) {
225
253
return m .latestApp .Info (req ) // Always use latest app for Info
226
254
}
227
255
228
- func (m * multiplexer ) InitChain (_ context.Context , req * abci.RequestInitChain ) (* abci.ResponseInitChain , error ) {
256
+ func (m * Multiplexer ) InitChain (_ context.Context , req * abci.RequestInitChain ) (* abci.ResponseInitChain , error ) {
229
257
app , err := m .getAppForHeight (0 )
230
258
if err != nil {
231
259
return nil , fmt .Errorf ("failed to get app for genesis: %w" , err )
232
260
}
233
261
return app .InitChain (req )
234
262
}
235
263
236
- func (m * multiplexer ) ListSnapshots (_ context.Context , req * abci.RequestListSnapshots ) (* abci.ResponseListSnapshots , error ) {
264
+ func (m * Multiplexer ) ListSnapshots (_ context.Context , req * abci.RequestListSnapshots ) (* abci.ResponseListSnapshots , error ) {
237
265
app , err := m .getAppForHeight (m .lastHeight )
238
266
if err != nil {
239
267
return nil , fmt .Errorf ("failed to get app for height %d: %w" , m .lastHeight , err )
240
268
}
241
269
return app .ListSnapshots (req )
242
270
}
243
271
244
- func (m * multiplexer ) LoadSnapshotChunk (_ context.Context , req * abci.RequestLoadSnapshotChunk ) (* abci.ResponseLoadSnapshotChunk , error ) {
272
+ func (m * Multiplexer ) LoadSnapshotChunk (_ context.Context , req * abci.RequestLoadSnapshotChunk ) (* abci.ResponseLoadSnapshotChunk , error ) {
245
273
app , err := m .getAppForHeight (int64 (req .Height ))
246
274
if err != nil {
247
275
return nil , fmt .Errorf ("failed to get app for height %d: %w" , req .Height , err )
248
276
}
249
277
return app .LoadSnapshotChunk (req )
250
278
}
251
279
252
- func (m * multiplexer ) OfferSnapshot (_ context.Context , req * abci.RequestOfferSnapshot ) (* abci.ResponseOfferSnapshot , error ) {
280
+ func (m * Multiplexer ) OfferSnapshot (_ context.Context , req * abci.RequestOfferSnapshot ) (* abci.ResponseOfferSnapshot , error ) {
253
281
app , err := m .getAppForHeight (m .lastHeight )
254
282
if err != nil {
255
283
return nil , fmt .Errorf ("failed to get app for height %d: %w" , m .lastHeight , err )
256
284
}
257
285
return app .OfferSnapshot (req )
258
286
}
259
287
260
- func (m * multiplexer ) PrepareProposal (_ context.Context , req * abci.RequestPrepareProposal ) (* abci.ResponsePrepareProposal , error ) {
288
+ func (m * Multiplexer ) PrepareProposal (_ context.Context , req * abci.RequestPrepareProposal ) (* abci.ResponsePrepareProposal , error ) {
261
289
m .lastHeight = req .Height
262
290
app , err := m .getAppForHeight (req .Height )
263
291
if err != nil {
@@ -266,7 +294,7 @@ func (m *multiplexer) PrepareProposal(_ context.Context, req *abci.RequestPrepar
266
294
return app .PrepareProposal (req )
267
295
}
268
296
269
- func (m * multiplexer ) ProcessProposal (_ context.Context , req * abci.RequestProcessProposal ) (* abci.ResponseProcessProposal , error ) {
297
+ func (m * Multiplexer ) ProcessProposal (_ context.Context , req * abci.RequestProcessProposal ) (* abci.ResponseProcessProposal , error ) {
270
298
m .lastHeight = req .Height
271
299
app , err := m .getAppForHeight (req .Height )
272
300
if err != nil {
@@ -275,15 +303,15 @@ func (m *multiplexer) ProcessProposal(_ context.Context, req *abci.RequestProces
275
303
return app .ProcessProposal (req )
276
304
}
277
305
278
- func (m * multiplexer ) Query (ctx context.Context , req * abci.RequestQuery ) (* abci.ResponseQuery , error ) {
306
+ func (m * Multiplexer ) Query (ctx context.Context , req * abci.RequestQuery ) (* abci.ResponseQuery , error ) {
279
307
app , err := m .getAppForHeight (req .Height )
280
308
if err != nil {
281
309
return nil , fmt .Errorf ("failed to get app for height %d: %w" , req .Height , err )
282
310
}
283
311
return app .Query (ctx , req )
284
312
}
285
313
286
- func (m * multiplexer ) VerifyVoteExtension (_ context.Context , req * abci.RequestVerifyVoteExtension ) (* abci.ResponseVerifyVoteExtension , error ) {
314
+ func (m * Multiplexer ) VerifyVoteExtension (_ context.Context , req * abci.RequestVerifyVoteExtension ) (* abci.ResponseVerifyVoteExtension , error ) {
287
315
m .lastHeight = req .Height
288
316
app , err := m .getAppForHeight (req .Height )
289
317
if err != nil {
0 commit comments