@@ -2,17 +2,22 @@ use std::os::fd::AsRawFd;
2
2
use std:: time:: Duration ;
3
3
use std:: { io, thread} ;
4
4
5
+ use bytes:: Bytes ;
5
6
use mio:: unix:: SourceFd ;
6
7
use mio:: { Events , Interest , Poll , Token } ;
7
8
use sled:: Tree ;
8
9
use thiserror:: Error ;
9
- use tungstenite:: Bytes ;
10
+ use tungstenite:: Utf8Bytes ;
11
+ use tungstenite:: protocol:: CloseFrame ;
12
+ use tungstenite:: protocol:: frame:: coding:: CloseCode ;
10
13
11
14
use crate :: publisher:: connection:: { Connection , ConnectionError } ;
12
15
use crate :: publisher:: types:: { Command , CommandReceiver } ;
13
16
use crate :: types:: { Cursor , DB } ;
14
17
15
18
const INTEREST : Interest = Interest :: WRITABLE ;
19
+ const SHUTDOWN_FRAME : CloseFrame =
20
+ CloseFrame { code : CloseCode :: Restart , reason : Utf8Bytes :: from_static ( "RelayRestart" ) } ;
16
21
17
22
#[ derive( Debug , Error ) ]
18
23
pub enum WorkerError {
@@ -27,6 +32,7 @@ pub enum WorkerError {
27
32
pub struct Worker {
28
33
id : usize ,
29
34
connections : Vec < Option < Connection > > ,
35
+ next_idx : usize ,
30
36
command_rx : CommandReceiver ,
31
37
firehose : Tree ,
32
38
poll : Poll ,
@@ -38,7 +44,7 @@ impl Worker {
38
44
let firehose = DB . open_tree ( "firehose" ) ?;
39
45
let poll = Poll :: new ( ) ?;
40
46
let events = Events :: with_capacity ( 1024 ) ;
41
- Ok ( Self { id, connections : Vec :: new ( ) , command_rx, firehose, poll, events } )
47
+ Ok ( Self { id, connections : Vec :: new ( ) , next_idx : 0 , command_rx, firehose, poll, events } )
42
48
}
43
49
44
50
pub fn run ( mut self ) -> Result < ( ) , WorkerError > {
@@ -53,7 +59,7 @@ impl Worker {
53
59
54
60
pub fn shutdown ( mut self ) {
55
61
for conn in self . connections . iter_mut ( ) . filter_map ( |x| x. as_mut ( ) ) {
56
- if let Err ( err) = conn. close ( ) {
62
+ if let Err ( err) = conn. close ( SHUTDOWN_FRAME ) {
57
63
tracing:: warn!( "publisher conn close error: {err}" ) ;
58
64
}
59
65
}
@@ -112,23 +118,24 @@ impl Worker {
112
118
}
113
119
114
120
let mut events = std:: mem:: replace ( & mut self . events , Events :: with_capacity ( 0 ) ) ;
115
- for _ in 0 ..32 {
121
+ ' outer : for _ in 0 ..32 {
116
122
#[ expect( clippy:: expect_used) ]
117
123
self . poll
118
124
. poll ( & mut events, Some ( Duration :: from_millis ( 1 ) ) )
119
125
. expect ( "failed to poll" ) ;
120
126
for ev in & events {
121
127
if !self . poll ( * seq, ev. token ( ) . 0 ) {
122
- return Ok ( false ) ;
128
+ break ' outer ;
123
129
}
124
130
}
125
131
}
126
132
self . events = events;
127
133
}
128
134
129
- for idx in 0 ..self . connections . len ( ) {
130
- if !self . poll ( * seq, idx) {
131
- return Ok ( false ) ;
135
+ for _ in 0 ..self . connections . len ( ) {
136
+ self . next_idx = ( self . next_idx + 1 ) % self . connections . len ( ) ;
137
+ if !self . poll ( * seq, self . next_idx ) {
138
+ break ;
132
139
}
133
140
}
134
141
@@ -154,16 +161,23 @@ impl Worker {
154
161
155
162
fn poll ( & mut self , seq : Cursor , idx : usize ) -> bool {
156
163
if let Some ( conn) = & mut self . connections [ idx] {
157
- if let Err ( err ) = conn. poll ( seq, & self . firehose ) {
158
- tracing :: info! ( "[{}] disconnected: {err}" , conn . addr ) ;
159
- # [ expect ( clippy :: expect_used ) ]
160
- self . poll
161
- . registry ( )
162
- . deregister ( & mut SourceFd ( & conn . as_raw_fd ( ) ) )
163
- . expect ( "failed to deregister" ) ;
164
- self . connections [ idx ] = None ;
164
+ match conn. poll ( seq, & self . firehose ) {
165
+ Ok ( true ) => return true ,
166
+ Ok ( false ) => {
167
+ tracing :: info! ( "[{}] closed due to invalid cursor" , conn . addr ) ;
168
+ }
169
+ Err ( err ) => {
170
+ tracing :: info! ( "[{}] disconnected: {err}" , conn . addr ) ;
171
+ }
165
172
}
173
+ #[ expect( clippy:: expect_used) ]
174
+ self . poll
175
+ . registry ( )
176
+ . deregister ( & mut SourceFd ( & conn. as_raw_fd ( ) ) )
177
+ . expect ( "failed to deregister" ) ;
178
+ self . connections [ idx] = None ;
166
179
}
180
+
167
181
true
168
182
}
169
183
}
0 commit comments