-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow RootContext to create child contexts for streams. #34
Changes from 3 commits
28ba351
94ecd03
1cad709
6488b8a
79e8621
5f0302c
9756371
46cf563
a4658e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,10 +18,23 @@ use proxy_wasm::types::*; | |
#[no_mangle] | ||
pub fn _start() { | ||
proxy_wasm::set_log_level(LogLevel::Trace); | ||
proxy_wasm::set_http_context(|_, _| -> Box<dyn HttpContext> { Box::new(HttpBody) }); | ||
proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> { Box::new(HttpBodyRoot) }); | ||
} | ||
|
||
struct HttpBody; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: move |
||
struct HttpBodyRoot; | ||
|
||
impl Context for HttpBodyRoot {} | ||
|
||
impl RootContext for HttpBodyRoot { | ||
fn get_type(&self) -> ContextType { | ||
ContextType::HttpContext | ||
} | ||
|
||
fn create_http_context(&self, _context_id: u32) -> Box<dyn HttpContext> { | ||
Box::new(HttpBody) | ||
} | ||
} | ||
|
||
impl Context for HttpBody {} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,14 +26,6 @@ pub(crate) fn set_root_context(callback: NewRootContext) { | |
DISPATCHER.with(|dispatcher| dispatcher.set_root_context(callback)); | ||
} | ||
|
||
pub(crate) fn set_stream_context(callback: NewStreamContext) { | ||
DISPATCHER.with(|dispatcher| dispatcher.set_stream_context(callback)); | ||
} | ||
|
||
pub(crate) fn set_http_context(callback: NewHttpContext) { | ||
DISPATCHER.with(|dispatcher| dispatcher.set_http_context(callback)); | ||
} | ||
|
||
pub(crate) fn register_callout(token_id: u32) { | ||
DISPATCHER.with(|dispatcher| dispatcher.register_callout(token_id)); | ||
} | ||
|
@@ -46,9 +38,7 @@ impl RootContext for NoopRoot {} | |
struct Dispatcher { | ||
new_root: Cell<Option<NewRootContext>>, | ||
roots: RefCell<HashMap<u32, Box<dyn RootContext>>>, | ||
new_stream: Cell<Option<NewStreamContext>>, | ||
streams: RefCell<HashMap<u32, Box<dyn StreamContext>>>, | ||
new_http_stream: Cell<Option<NewHttpContext>>, | ||
http_streams: RefCell<HashMap<u32, Box<dyn HttpContext>>>, | ||
active_id: Cell<u32>, | ||
callouts: RefCell<HashMap<u32, u32>>, | ||
|
@@ -59,9 +49,7 @@ impl Dispatcher { | |
Dispatcher { | ||
new_root: Cell::new(None), | ||
roots: RefCell::new(HashMap::new()), | ||
new_stream: Cell::new(None), | ||
streams: RefCell::new(HashMap::new()), | ||
new_http_stream: Cell::new(None), | ||
http_streams: RefCell::new(HashMap::new()), | ||
active_id: Cell::new(0), | ||
callouts: RefCell::new(HashMap::new()), | ||
|
@@ -72,12 +60,15 @@ impl Dispatcher { | |
self.new_root.set(Some(callback)); | ||
} | ||
|
||
fn set_stream_context(&self, callback: NewStreamContext) { | ||
self.new_stream.set(Some(callback)); | ||
} | ||
|
||
fn set_http_context(&self, callback: NewHttpContext) { | ||
self.new_http_stream.set(Some(callback)); | ||
fn register_callout(&self, token_id: u32) { | ||
if self | ||
.callouts | ||
.borrow_mut() | ||
.insert(token_id, self.active_id.get()) | ||
.is_some() | ||
{ | ||
panic!("duplicate token_id") | ||
} | ||
} | ||
|
||
fn create_root_context(&self, context_id: u32) { | ||
|
@@ -96,12 +87,9 @@ impl Dispatcher { | |
} | ||
|
||
fn create_stream_context(&self, context_id: u32, root_context_id: u32) { | ||
if !self.roots.borrow().contains_key(&root_context_id) { | ||
panic!("invalid root_context_id") | ||
} | ||
let new_context = match self.new_stream.get() { | ||
Some(f) => f(context_id, root_context_id), | ||
None => panic!("missing constructor"), | ||
let new_context = match self.roots.borrow().get(&root_context_id) { | ||
Some(root_context) => root_context.create_stream_context(context_id), | ||
None => panic!("invalid root_context_id"), | ||
}; | ||
if self | ||
.streams | ||
|
@@ -114,12 +102,9 @@ impl Dispatcher { | |
} | ||
|
||
fn create_http_context(&self, context_id: u32, root_context_id: u32) { | ||
if !self.roots.borrow().contains_key(&root_context_id) { | ||
panic!("invalid root_context_id") | ||
} | ||
let new_context = match self.new_http_stream.get() { | ||
Some(f) => f(context_id, root_context_id), | ||
None => panic!("missing constructor"), | ||
let new_context = match self.roots.borrow().get(&root_context_id) { | ||
Some(root_context) => root_context.create_http_context(context_id), | ||
None => panic!("invalid root_context_id"), | ||
}; | ||
if self | ||
.http_streams | ||
|
@@ -131,26 +116,19 @@ impl Dispatcher { | |
} | ||
} | ||
|
||
fn register_callout(&self, token_id: u32) { | ||
if self | ||
.callouts | ||
.borrow_mut() | ||
.insert(token_id, self.active_id.get()) | ||
.is_some() | ||
{ | ||
panic!("duplicate token_id") | ||
} | ||
} | ||
|
||
fn on_create_context(&self, context_id: u32, root_context_id: u32) { | ||
if root_context_id == 0 { | ||
self.create_root_context(context_id) | ||
} else if self.new_http_stream.get().is_some() { | ||
self.create_http_context(context_id, root_context_id); | ||
} else if self.new_stream.get().is_some() { | ||
self.create_stream_context(context_id, root_context_id); | ||
self.create_root_context(context_id); | ||
} else if let Some(root_context) = self.roots.borrow().get(&root_context_id) { | ||
match root_context.get_type() { | ||
ContextType::HttpContext => self.create_http_context(context_id, root_context_id), | ||
ContextType::StreamContext => { | ||
self.create_stream_context(context_id, root_context_id) | ||
} | ||
PiotrSikora marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ContextType::RootContext => panic!("missing ContextType on root_context"), | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One more thing. I think it would be useful if we could retain backwards compatibility, and merge this without breaking all existing plugins, even if there aren't too many in the wild right now. One way to do this is to fallback to the standalone constructors in case There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 to remain backwards-compatible, but I think we should then deprecate the old way to create contexts and remove it in 0.2.0 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that would also allow us to remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "old way" is fine for plugins that don't have configuration (e.g. where everything is already in the code), and the "new way" can double the code size with unnecessary boilerplate. But it's something to consider for sure. |
||
} else { | ||
panic!("missing constructors") | ||
panic!("invalid root_context_id"); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -121,6 +121,18 @@ pub trait RootContext: Context { | |
fn on_queue_ready(&mut self, _queue_id: u32) {} | ||
|
||
fn on_log(&mut self) {} | ||
|
||
fn create_http_context(&self, _context_id: u32) -> Box<dyn HttpContext> { | ||
Box::new(EmptyHttpContext) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} | ||
|
||
fn create_stream_context(&self, _context_id: u32) -> Box<dyn StreamContext> { | ||
Box::new(EmptyStreamContext) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} | ||
|
||
fn get_type(&self) -> ContextType { | ||
ContextType::RootContext | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
PiotrSikora marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
pub trait StreamContext: Context { | ||
|
@@ -159,6 +171,11 @@ pub trait StreamContext: Context { | |
fn on_log(&mut self) {} | ||
} | ||
|
||
struct EmptyStreamContext; | ||
|
||
impl StreamContext for EmptyStreamContext {} | ||
impl Context for EmptyStreamContext {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This won't be needed with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
pub trait HttpContext: Context { | ||
fn on_http_request_headers(&mut self, _num_headers: usize) -> Action { | ||
Action::Continue | ||
|
@@ -303,3 +320,8 @@ pub trait HttpContext: Context { | |
|
||
fn on_log(&mut self) {} | ||
} | ||
|
||
struct EmptyHttpContext; | ||
|
||
impl HttpContext for EmptyHttpContext {} | ||
impl Context for EmptyHttpContext {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This won't be needed with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,3 +85,9 @@ pub enum MetricType { | |
} | ||
|
||
pub type Bytes = Vec<u8>; | ||
|
||
pub enum ContextType { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add:
(it's not used in the ABI right now, but it's going to be soon, so we might as well define it properly now) Also, could you move it below There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
RootContext = 0, | ||
HttpContext = 1, | ||
StreamContext = 2, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this example, I wonder if we couldn't do something type-specific here, e.g.
with dispatcher taking care of resolving
root_context_id
toroot_context
before calling this callback?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the second thought, that might be useless, since we cannot expose multiple interfaces right now anyway.