refactor(plugins): harden target-plugin system and admin plugin contract (#4217)

This commit is contained in:
Zhengchao An
2026-07-03 10:18:21 +08:00
committed by GitHub
parent c260a2f20f
commit fb0e2d6d8f
30 changed files with 683 additions and 328 deletions
+7 -8
View File
@@ -16,10 +16,9 @@ use super::{
ReplayEvent, ReplayWorkerManager, RuntimeActivation, RuntimeStatusSnapshot, RuntimeTargetHealthSnapshot,
TargetRuntimeManager, activate_targets_with_replay, init_target_and_optionally_start_replay, start_replay_worker,
};
use crate::plugin::PluginEvent;
use crate::{Target, TargetError};
use async_trait::async_trait;
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
@@ -33,7 +32,7 @@ type ReplayStartObserver = Arc<dyn Fn(&str, bool) + Send + Sync>;
#[async_trait]
pub trait PluginRuntimeAdapter<E>: Send + Sync
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
async fn activate_with_replay(&self, targets: Vec<Box<dyn Target<E> + Send + Sync>>) -> RuntimeActivation<E>;
@@ -66,7 +65,7 @@ where
#[derive(Clone)]
pub struct BuiltinPluginRuntimeAdapter<E>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
replay_hook: ReplayHook<E>,
replay_start_observer: ReplayStartObserver,
@@ -78,7 +77,7 @@ where
impl<E> BuiltinPluginRuntimeAdapter<E>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
pub fn new(
replay_hook: ReplayHook<E>,
@@ -102,7 +101,7 @@ where
#[async_trait]
impl<E> PluginRuntimeAdapter<E> for BuiltinPluginRuntimeAdapter<E>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
async fn activate_with_replay(&self, targets: Vec<Box<dyn Target<E> + Send + Sync>>) -> RuntimeActivation<E> {
let replay_hook = Arc::clone(&self.replay_hook);
@@ -184,12 +183,12 @@ where
#[cfg(test)]
mod tests {
use super::{BuiltinPluginRuntimeAdapter, PluginRuntimeAdapter};
use crate::PluginEvent;
use crate::arn::TargetID;
use crate::store::{Key, QueueStore, Store};
use crate::target::{EntityTarget, QueuedPayload, QueuedPayloadMeta};
use crate::{StoreError, Target, TargetError};
use async_trait::async_trait;
use serde::{Serialize, de::DeserializeOwned};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
@@ -230,7 +229,7 @@ mod tests {
#[async_trait]
impl<E> Target<E> for TestTarget
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
fn id(&self) -> TargetID {
self.id.clone()
+14 -15
View File
@@ -22,12 +22,11 @@ pub mod tls;
use crate::Target;
use crate::arn::TargetID;
use crate::plugin::PluginEvent;
use crate::store::{Key, Store, ensure_store_entry_raw_readable};
use crate::target::QueuedPayload;
use crate::target::TargetDeliverySnapshot;
use crate::{StoreError, TargetError};
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::sync::Arc;
use std::{collections::HashMap, fmt::Debug};
use std::{future::Future, pin::Pin, time::Duration};
@@ -78,7 +77,7 @@ impl ReplayWorkerManager {
pub struct RuntimeActivation<E>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
pub replay_workers: ReplayWorkerManager,
pub targets: Vec<SharedTarget<E>>,
@@ -119,7 +118,7 @@ pub struct RuntimeTargetHealthSnapshot {
pub enum ReplayEvent<E>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
Delivered {
key: Key,
@@ -159,14 +158,14 @@ where
/// be layered on top in later phases.
pub struct TargetRuntimeManager<E>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
targets: HashMap<String, SharedTarget<E>>,
}
impl<E> Default for TargetRuntimeManager<E>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
fn default() -> Self {
Self::new()
@@ -175,7 +174,7 @@ where
impl<E> Debug for TargetRuntimeManager<E>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TargetRuntimeManager")
@@ -186,7 +185,7 @@ where
impl<E> TargetRuntimeManager<E>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
pub fn new() -> Self {
Self { targets: HashMap::new() }
@@ -320,7 +319,7 @@ pub async fn init_target_and_optionally_start_replay<E, F, G>(
start_replay: G,
) -> Option<(SharedTarget<E>, Option<mpsc::Sender<()>>)>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
F: FnOnce(&str, bool),
G: FnOnce(Box<dyn Store<QueuedPayload, Error = StoreError, Key = Key> + Send>, SharedTarget<E>) -> mpsc::Sender<()>,
{
@@ -356,7 +355,7 @@ pub async fn activate_targets_with_replay<E, F, Fut>(
mut activate_one: F,
) -> RuntimeActivation<E>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
F: FnMut(Box<dyn Target<E> + Send + Sync>) -> Fut,
Fut: Future<Output = Option<(SharedTarget<E>, Option<mpsc::Sender<()>>)>>,
{
@@ -388,7 +387,7 @@ pub fn start_replay_worker<E>(
idle_sleep: Duration,
) -> mpsc::Sender<()>
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
let (cancel_tx, cancel_rx) = mpsc::channel(1);
@@ -408,7 +407,7 @@ async fn stream_replay_worker<E>(
batch_timeout: Duration,
idle_sleep: Duration,
) where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
const MAX_RETRIES: usize = 5;
const BASE_RETRY_DELAY: Duration = Duration::from_secs(2);
@@ -469,7 +468,7 @@ async fn stream_replay_worker<E>(
hook: &ReplayHook<E>,
semaphore: Option<Arc<Semaphore>>,
) where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
if batch_keys.is_empty() {
return;
@@ -553,13 +552,13 @@ async fn stream_replay_worker<E>(
#[cfg(test)]
mod tests {
use super::TargetRuntimeManager;
use crate::PluginEvent;
use crate::StoreError;
use crate::arn::TargetID;
use crate::store::{Key, Store};
use crate::target::{EntityTarget, QueuedPayload, QueuedPayloadMeta};
use crate::{Target, TargetError};
use async_trait::async_trait;
use serde::{Serialize, de::DeserializeOwned};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -581,7 +580,7 @@ mod tests {
#[async_trait]
impl<E> Target<E> for TestTarget
where
E: Send + Sync + 'static + Clone + Serialize + DeserializeOwned,
E: PluginEvent,
{
fn id(&self) -> TargetID {
self.id.clone()