Skip to content

Commit 2e17e21

Browse files
authored
feat: send metadata (#27)
1 parent a88d83b commit 2e17e21

7 files changed

+243
-25
lines changed

config/geyser-plugin-config.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"libpath": "../target/release/libsolana_geyser_plugin_scaffold.so",
33
"tcp_port": 2000,
4-
"tcp_buffer_size": 500,
4+
"tcp_buffer_size": 5000,
55
"tcp_batch_max_bytes": 2097152,
66
"send_transactions": true,
77
"send_accounts": true,

src/errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use thiserror::Error;
33
#[derive(Error, Debug)]
44
pub enum GeyserError {
55
#[error("tcp send error")]
6-
TcpSend(usize),
6+
TcpSend(u64),
77

88
#[error("cannot acquire sender lock")]
99
SenderLockError,

src/flatbuffer/metadata.fbs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Metadata;
2+
3+
table Metadata {
4+
send_errors: ulong;
5+
}
6+
7+
root_type Metadata;

src/flatbuffer/metadata_generated.rs

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
// automatically generated by the FlatBuffers compiler, do not modify
2+
3+
// @generated
4+
5+
extern crate flatbuffers;
6+
7+
#[allow(unused_imports, dead_code)]
8+
pub mod metadata {
9+
10+
use core::cmp::Ordering;
11+
use core::mem;
12+
13+
extern crate flatbuffers;
14+
use self::flatbuffers::{EndianScalar, Follow};
15+
16+
pub enum MetadataOffset {}
17+
#[derive(Copy, Clone, PartialEq)]
18+
19+
pub struct Metadata<'a> {
20+
pub _tab: flatbuffers::Table<'a>,
21+
}
22+
23+
impl<'a> flatbuffers::Follow<'a> for Metadata<'a> {
24+
type Inner = Metadata<'a>;
25+
#[inline]
26+
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
27+
Self {
28+
_tab: flatbuffers::Table::new(buf, loc),
29+
}
30+
}
31+
}
32+
33+
impl<'a> Metadata<'a> {
34+
pub const VT_SEND_ERRORS: flatbuffers::VOffsetT = 4;
35+
36+
#[inline]
37+
pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
38+
Metadata { _tab: table }
39+
}
40+
#[allow(unused_mut)]
41+
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
42+
_fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,
43+
args: &'args MetadataArgs,
44+
) -> flatbuffers::WIPOffset<Metadata<'bldr>> {
45+
let mut builder = MetadataBuilder::new(_fbb);
46+
builder.add_send_errors(args.send_errors);
47+
builder.finish()
48+
}
49+
50+
#[inline]
51+
pub fn send_errors(&self) -> u64 {
52+
// Safety:
53+
// Created from valid Table for this object
54+
// which contains a valid value in this slot
55+
unsafe {
56+
self._tab
57+
.get::<u64>(Metadata::VT_SEND_ERRORS, Some(0))
58+
.unwrap()
59+
}
60+
}
61+
}
62+
63+
impl flatbuffers::Verifiable for Metadata<'_> {
64+
#[inline]
65+
fn run_verifier(
66+
v: &mut flatbuffers::Verifier,
67+
pos: usize,
68+
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
69+
use self::flatbuffers::Verifiable;
70+
v.visit_table(pos)?
71+
.visit_field::<u64>("send_errors", Self::VT_SEND_ERRORS, false)?
72+
.finish();
73+
Ok(())
74+
}
75+
}
76+
pub struct MetadataArgs {
77+
pub send_errors: u64,
78+
}
79+
impl<'a> Default for MetadataArgs {
80+
#[inline]
81+
fn default() -> Self {
82+
MetadataArgs { send_errors: 0 }
83+
}
84+
}
85+
86+
pub struct MetadataBuilder<'a: 'b, 'b> {
87+
fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,
88+
start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>,
89+
}
90+
impl<'a: 'b, 'b> MetadataBuilder<'a, 'b> {
91+
#[inline]
92+
pub fn add_send_errors(&mut self, send_errors: u64) {
93+
self.fbb_
94+
.push_slot::<u64>(Metadata::VT_SEND_ERRORS, send_errors, 0);
95+
}
96+
#[inline]
97+
pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> MetadataBuilder<'a, 'b> {
98+
let start = _fbb.start_table();
99+
MetadataBuilder {
100+
fbb_: _fbb,
101+
start_: start,
102+
}
103+
}
104+
#[inline]
105+
pub fn finish(self) -> flatbuffers::WIPOffset<Metadata<'a>> {
106+
let o = self.fbb_.end_table(self.start_);
107+
flatbuffers::WIPOffset::new(o.value())
108+
}
109+
}
110+
111+
impl core::fmt::Debug for Metadata<'_> {
112+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
113+
let mut ds = f.debug_struct("Metadata");
114+
ds.field("send_errors", &self.send_errors());
115+
ds.finish()
116+
}
117+
}
118+
#[inline]
119+
/// Verifies that a buffer of bytes contains a `Metadata`
120+
/// and returns it.
121+
/// Note that verification is still experimental and may not
122+
/// catch every error, or be maximally performant. For the
123+
/// previous, unchecked, behavior use
124+
/// `root_as_metadata_unchecked`.
125+
pub fn root_as_metadata(buf: &[u8]) -> Result<Metadata, flatbuffers::InvalidFlatbuffer> {
126+
flatbuffers::root::<Metadata>(buf)
127+
}
128+
#[inline]
129+
/// Verifies that a buffer of bytes contains a size prefixed
130+
/// `Metadata` and returns it.
131+
/// Note that verification is still experimental and may not
132+
/// catch every error, or be maximally performant. For the
133+
/// previous, unchecked, behavior use
134+
/// `size_prefixed_root_as_metadata_unchecked`.
135+
pub fn size_prefixed_root_as_metadata(
136+
buf: &[u8],
137+
) -> Result<Metadata, flatbuffers::InvalidFlatbuffer> {
138+
flatbuffers::size_prefixed_root::<Metadata>(buf)
139+
}
140+
#[inline]
141+
/// Verifies, with the given options, that a buffer of bytes
142+
/// contains a `Metadata` and returns it.
143+
/// Note that verification is still experimental and may not
144+
/// catch every error, or be maximally performant. For the
145+
/// previous, unchecked, behavior use
146+
/// `root_as_metadata_unchecked`.
147+
pub fn root_as_metadata_with_opts<'b, 'o>(
148+
opts: &'o flatbuffers::VerifierOptions,
149+
buf: &'b [u8],
150+
) -> Result<Metadata<'b>, flatbuffers::InvalidFlatbuffer> {
151+
flatbuffers::root_with_opts::<Metadata<'b>>(opts, buf)
152+
}
153+
#[inline]
154+
/// Verifies, with the given verifier options, that a buffer of
155+
/// bytes contains a size prefixed `Metadata` and returns
156+
/// it. Note that verification is still experimental and may not
157+
/// catch every error, or be maximally performant. For the
158+
/// previous, unchecked, behavior use
159+
/// `root_as_metadata_unchecked`.
160+
pub fn size_prefixed_root_as_metadata_with_opts<'b, 'o>(
161+
opts: &'o flatbuffers::VerifierOptions,
162+
buf: &'b [u8],
163+
) -> Result<Metadata<'b>, flatbuffers::InvalidFlatbuffer> {
164+
flatbuffers::size_prefixed_root_with_opts::<Metadata<'b>>(opts, buf)
165+
}
166+
#[inline]
167+
/// Assumes, without verification, that a buffer of bytes contains a Metadata and returns it.
168+
/// # Safety
169+
/// Callers must trust the given bytes do indeed contain a valid `Metadata`.
170+
pub unsafe fn root_as_metadata_unchecked(buf: &[u8]) -> Metadata {
171+
flatbuffers::root_unchecked::<Metadata>(buf)
172+
}
173+
#[inline]
174+
/// Assumes, without verification, that a buffer of bytes contains a size prefixed Metadata and returns it.
175+
/// # Safety
176+
/// Callers must trust the given bytes do indeed contain a valid size prefixed `Metadata`.
177+
pub unsafe fn size_prefixed_root_as_metadata_unchecked(buf: &[u8]) -> Metadata {
178+
flatbuffers::size_prefixed_root_unchecked::<Metadata>(buf)
179+
}
180+
#[inline]
181+
pub fn finish_metadata_buffer<'a, 'b>(
182+
fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,
183+
root: flatbuffers::WIPOffset<Metadata<'a>>,
184+
) {
185+
fbb.finish(root, None);
186+
}
187+
188+
#[inline]
189+
pub fn finish_size_prefixed_metadata_buffer<'a, 'b>(
190+
fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,
191+
root: flatbuffers::WIPOffset<Metadata<'a>>,
192+
) {
193+
fbb.finish_size_prefixed(root, None);
194+
}
195+
} // pub mod Metadata

src/flatbuffer/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use solana_program::pubkey::Pubkey;
2323
use solana_sdk::signature::Signature;
2424
use solana_transaction_status::{UiReturnDataEncoding, UiTransactionReturnData};
2525

26+
use self::metadata_generated::metadata::{Metadata, MetadataArgs};
2627
use self::{
2728
block_info_generated::block_info::{BlockInfo, BlockInfoArgs},
2829
common_generated::common::{Reward, RewardArgs, RewardType},
@@ -36,6 +37,8 @@ mod block_info_generated;
3637
#[allow(dead_code, clippy::all)]
3738
mod common_generated;
3839
#[allow(dead_code, clippy::all)]
40+
mod metadata_generated;
41+
#[allow(dead_code, clippy::all)]
3942
mod slot_generated;
4043
#[allow(dead_code, clippy::all)]
4144
mod transaction_info_generated;
@@ -47,6 +50,7 @@ const BYTE_PREFIX_ACCOUNT: u8 = 0;
4750
const BYTE_PREFIX_SLOT: u8 = 1;
4851
const BYTE_PREFIX_TX: u8 = 2;
4952
const BYTE_PREFIX_BLOCK: u8 = 3;
53+
const BYTE_PREFIX_METADATA: u8 = 4;
5054

5155
pub struct AccountUpdate {
5256
/// The account's public key
@@ -1341,3 +1345,15 @@ pub fn serialize_transaction(transaction: &TransactionUpdate) -> Result<Vec<u8>,
13411345

13421346
Ok(output)
13431347
}
1348+
1349+
pub fn serialize_metadata(send_errors: u64) -> Vec<u8> {
1350+
let mut builder = FlatBufferBuilder::new();
1351+
1352+
let obj = Metadata::create(&mut builder, &MetadataArgs { send_errors });
1353+
builder.finish(obj, None);
1354+
1355+
let mut output = vec![BYTE_PREFIX_METADATA];
1356+
output.extend(builder.finished_data().to_vec());
1357+
1358+
output
1359+
}

src/geyser_plugin_hook.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,22 @@ impl GeyserPlugin for GeyserPluginHook {
101101

102102
info!("[on_load] - socket created");
103103

104-
self.0 = Some(Arc::new(Inner {
104+
let plugin = Arc::new(Inner {
105105
socket,
106106
metrics: metrics.clone(),
107107
config: cfg,
108-
}));
108+
});
109+
110+
self.0 = Some(plugin.clone());
111+
112+
thread::spawn(move || loop {
113+
let data = flatbuffer::serialize_metadata(metrics.send_errs.load(Ordering::Relaxed));
114+
if let Err(e) = plugin.socket.publish(data) {
115+
info!("{}", e);
116+
}
109117

110-
thread::spawn(move || {
111-
metrics.spin(Duration::from_secs(10));
118+
info!("{}", metrics);
119+
thread::sleep(Duration::from_secs(10));
112120
});
113121

114122
Ok(())

src/metrics.rs

+11-19
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,23 @@
1-
use log::info;
2-
use std::{fmt, sync::Arc, thread, time};
1+
use std::{fmt, sync::Arc};
32

43
pub struct Metrics {
5-
pub send_errs: std::sync::atomic::AtomicUsize,
6-
pub serialize_errs: std::sync::atomic::AtomicUsize,
7-
pub sender_lock_errs: std::sync::atomic::AtomicUsize,
8-
pub conn_lock_errs: std::sync::atomic::AtomicUsize,
9-
pub untyped_errs: std::sync::atomic::AtomicUsize,
4+
pub send_errs: std::sync::atomic::AtomicU64,
5+
pub serialize_errs: std::sync::atomic::AtomicU64,
6+
pub sender_lock_errs: std::sync::atomic::AtomicU64,
7+
pub conn_lock_errs: std::sync::atomic::AtomicU64,
8+
pub untyped_errs: std::sync::atomic::AtomicU64,
109
}
1110

1211
impl Metrics {
1312
pub fn new_rc() -> Arc<Self> {
1413
Arc::new(Self {
15-
send_errs: std::sync::atomic::AtomicUsize::new(0),
16-
serialize_errs: std::sync::atomic::AtomicUsize::new(0),
17-
sender_lock_errs: std::sync::atomic::AtomicUsize::new(0),
18-
conn_lock_errs: std::sync::atomic::AtomicUsize::new(0),
19-
untyped_errs: std::sync::atomic::AtomicUsize::new(0),
14+
send_errs: std::sync::atomic::AtomicU64::new(0),
15+
serialize_errs: std::sync::atomic::AtomicU64::new(0),
16+
sender_lock_errs: std::sync::atomic::AtomicU64::new(0),
17+
conn_lock_errs: std::sync::atomic::AtomicU64::new(0),
18+
untyped_errs: std::sync::atomic::AtomicU64::new(0),
2019
})
2120
}
22-
23-
pub fn spin(&self, interval: time::Duration) {
24-
loop {
25-
info!("{}", self);
26-
thread::sleep(interval)
27-
}
28-
}
2921
}
3022

3123
impl std::fmt::Display for Metrics {

0 commit comments

Comments
 (0)