@@ -7,6 +7,7 @@ using namespace pc;
7
7
#define PC_RPC_WEBSOCKET_PORT 8900
8
8
#define PC_RECONNECT_TIMEOUT (120L *1000000000L )
9
9
#define PC_BLOCKHASH_TIMEOUT 3
10
+ #define PC_PUB_INTERVAL (293L *PC_NSECS_IN_MSEC)
10
11
11
12
// /////////////////////////////////////////////////////////////////////////
12
13
// manager_sub
@@ -39,17 +40,17 @@ manager::manager()
39
40
status_( 0 ),
40
41
num_sub_( 0 ),
41
42
version_( PC_VERSION ),
42
- kidx_( 0 ),
43
+ kidx_( ( unsigned )-1 ),
43
44
cts_( 0L ),
44
45
ctimeout_( PC_NSECS_IN_SEC ),
45
- slot_ts_( 0L ),
46
- slot_int_( 0L ),
47
- slot_min_( 0L ),
48
46
slot_( 0UL ),
49
47
slot_cnt_( 0UL ),
48
+ curr_ts_( 0L ),
49
+ pub_ts_( 0L ),
50
+ pub_int_( PC_PUB_INTERVAL ),
50
51
wait_conn_( false ),
51
52
do_cap_( false ),
52
- first_ack_( true )
53
+ is_pub_( false )
53
54
{
54
55
breq_->set_sub ( this );
55
56
sreq_->set_sub ( this );
@@ -105,6 +106,16 @@ std::string manager::get_capture_file() const
105
106
return cap_.get_file ();
106
107
}
107
108
109
+ void manager::set_publish_interval ( int64_t pub_int )
110
+ {
111
+ pub_int_ = pub_int * PC_NSECS_IN_MSEC;
112
+ }
113
+
114
+ int64_t manager::get_publish_interval () const
115
+ {
116
+ return pub_int_ / PC_NSECS_IN_MSEC;
117
+ }
118
+
108
119
void manager::set_do_capture ( bool do_cap )
109
120
{
110
121
do_cap_ = do_cap;
@@ -155,6 +166,11 @@ manager_sub *manager::get_manager_sub() const
155
166
return sub_;
156
167
}
157
168
169
+ int64_t manager::get_curr_time () const
170
+ {
171
+ return curr_ts_;
172
+ }
173
+
158
174
rpc_client *manager::get_rpc_client ()
159
175
{
160
176
return &clnt_;
@@ -170,16 +186,6 @@ uint64_t manager::get_slot() const
170
186
return slot_;
171
187
}
172
188
173
- int64_t manager::get_slot_time () const
174
- {
175
- return slot_ts_;
176
- }
177
-
178
- int64_t manager::get_slot_interval () const
179
- {
180
- return slot_int_;
181
- }
182
-
183
189
void manager::teardown ()
184
190
{
185
191
PC_LOG_INF ( " pythd_teardown" ).end ();
@@ -258,6 +264,7 @@ bool manager::init()
258
264
PC_LOG_INF ( " initialized" )
259
265
.add ( " version" , version_ )
260
266
.add ( " capture_file" , get_capture_file () )
267
+ .add ( " publish_interval(ms)" , get_publish_interval () )
261
268
.end ();
262
269
263
270
return true ;
@@ -347,24 +354,30 @@ void manager::poll( bool do_wait )
347
354
// destroy any users scheduled for deletion
348
355
teardown_users ();
349
356
350
- // check if we need to reconnect rpc services
351
- if ( PC_UNLIKELY ( !has_status ( PC_PYTH_RPC_CONNECTED ) ||
352
- hconn_.get_is_err () || wconn_.get_is_err () )) {
357
+ // get current time
358
+ curr_ts_ = get_now ();
359
+
360
+ // submit new quotes while connected
361
+ if ( has_status ( PC_PYTH_RPC_CONNECTED ) &&
362
+ !hconn_.get_is_err () &&
363
+ !wconn_.get_is_err () ) {
364
+ poll_schedule ();
365
+ } else {
353
366
reconnect_rpc ();
354
- return ;
355
367
}
368
+ }
356
369
357
- // schedule next price update but only if we're connected to rpc port
358
- int64_t ts = get_now ();
359
- while ( kidx_ < kvec_.size () ) {
370
+ void manager::poll_schedule ()
371
+ {
372
+ while ( is_pub_ && kidx_ < kvec_.size () ) {
360
373
price_sched *kptr = kvec_[kidx_];
361
- int64_t tot_ts = slot_min_ - ack_ts_ - ack_ts_;
362
- tot_ts = std::max ( slot_min_/10 , tot_ts );
363
- int64_t pub_ts = slot_ts_ + ( tot_ts * kptr->get_hash () ) /
374
+ int64_t pub_ts = pub_ts_ + ( pub_int_ * kptr->get_hash () ) /
364
375
price_sched::fraction;
365
- if ( ts > pub_ts ) {
376
+ if ( curr_ts_ > pub_ts ) {
366
377
kptr->schedule ();
367
- ++kidx_;
378
+ if ( ++kidx_ >= kvec_.size () ) {
379
+ is_pub_ = false ;
380
+ }
368
381
} else {
369
382
break ;
370
383
}
@@ -391,15 +404,17 @@ void manager::reconnect_rpc()
391
404
392
405
// reset state
393
406
wait_conn_ = false ;
394
- first_ack_ = true ;
407
+ is_pub_ = false ;
408
+ kidx_ = 0 ;
395
409
ctimeout_ = PC_NSECS_IN_SEC;
396
- slot_ts_ = slot_int_ = 0L ;
410
+ pub_ts_ = 0L ;
397
411
slot_cnt_ = 0UL ;
412
+ slot_ = 0L ;
398
413
num_sub_ = 0 ;
399
414
clnt_.reset ();
400
415
plist_.clear ();
401
416
402
- // resubmit slot subscription
417
+ // subscribe to slots and get first block hash
403
418
clnt_.send ( sreq_ );
404
419
405
420
// resubscribe to mapping and symbol accounts
@@ -419,6 +434,13 @@ void manager::reconnect_rpc()
419
434
add_map_sub ();
420
435
}
421
436
}
437
+
438
+ // subscribe to mapping account if not done before
439
+ pub_key *mpub = get_mapping_pub_key ();
440
+ if ( mvec_.empty () && mpub ) {
441
+ add_mapping ( *mpub );
442
+ }
443
+
422
444
// callback user with connection status
423
445
if ( sub_ ) {
424
446
sub_->on_connect ( this );
@@ -518,36 +540,31 @@ void manager::schedule( price_sched *kptr )
518
540
519
541
void manager::on_response ( rpc::slot_subscribe *res )
520
542
{
521
- if ( !slot_ts_ ) {
522
- slot_ts_ = res->get_recv_time ();
543
+ // ignore slots that go back in time
544
+ uint64_t slot = res->get_slot ();
545
+ int64_t ts = res->get_recv_time ();
546
+ if ( slot <= slot_ ) {
523
547
return ;
524
548
}
525
- slot_ = res->get_slot ();
526
- slot_int_ = res->get_recv_time () - slot_ts_;
527
- slot_ts_ = res->get_recv_time ();
549
+ slot_ = slot;
550
+ PC_LOG_DBG ( " receive slot" ).add ( " slot" , slot_ ).end ();
551
+
552
+ // submit block hash every N slots
528
553
if ( slot_cnt_++ % PC_BLOCKHASH_TIMEOUT == 0 ) {
529
- // submit block hash every N slots
530
554
clnt_.send ( breq_ );
531
555
}
532
- // reset scheduler
533
- kidx_ = 0 ;
534
556
535
- // derive minimum slot interval
536
- if ( slot_min_ ) {
537
- slot_min_ = std::min ( slot_int_, slot_min_ ) ;
538
- } else {
539
- slot_min_ = slot_int_ ;
557
+ // reset submit
558
+ if ( !is_pub_ ) {
559
+ kidx_ = 0 ;
560
+ pub_ts_ = ts;
561
+ is_pub_ = true ;
540
562
}
541
563
542
564
// flush capture
543
565
if ( do_cap_ ) {
544
566
cap_.flush ();
545
567
}
546
- PC_LOG_DBG ( " receive slot" )
547
- .add ( " slot_num" , res->get_slot () )
548
- .add ( " slot_int" , 1e-6 *slot_int_ )
549
- .add ( " slot_min" , 1e-6 *slot_min_ )
550
- .end ();
551
568
}
552
569
553
570
void manager::on_response ( rpc::get_recent_block_hash *m )
@@ -557,30 +574,18 @@ void manager::on_response( rpc::get_recent_block_hash *m )
557
574
+ m->get_err_msg () + " ]" );
558
575
return ;
559
576
}
560
- static const double afactor = 2 ./(1 +8 .);
561
577
int64_t ack_ts = m->get_recv_time () - m->get_sent_time ();
562
- if ( !first_ack_ ) {
563
- ack_ts_ = (1 .-afactor)*ack_ts_ + afactor * ack_ts;
564
- } else {
565
- ack_ts_ = ack_ts;
566
- first_ack_ = false ;
567
- }
568
578
if ( has_status ( PC_PYTH_HAS_BLOCK_HASH ) ) {
569
579
return ;
570
580
}
571
581
// set initialized status for block hash
572
582
set_status ( PC_PYTH_HAS_BLOCK_HASH );
573
583
PC_LOG_INF ( " received_recent_block_hash" )
574
- .add ( " slot " , m-> get_slot () )
575
- .add ( " slot_interval(ms) " , 1e-6 *slot_int_ )
576
- .add ( " rount_trip_time(ms)" , 1e-6 *ack_ts_ )
584
+ .add ( " curr_slot " , slot_ )
585
+ .add ( " hash_slot " , m-> get_slot () )
586
+ .add ( " rount_trip_time(ms)" , 1e-6 *ack_ts )
577
587
.end ();
578
588
579
- // subscribe to mapping account if not done before
580
- pub_key *mpub = get_mapping_pub_key ();
581
- if ( mvec_.empty () && mpub ) {
582
- add_mapping ( *mpub );
583
- }
584
589
}
585
590
586
591
void manager::submit ( request *req )
0 commit comments