11package io .roastedroot .proxywasm ;
22
3- import static io .roastedroot .proxywasm .internal .Helpers .bytes ;
4-
5- import com .dylibso .chicory .runtime .ImportMemory ;
6- import com .dylibso .chicory .runtime .Instance ;
7- import com .dylibso .chicory .runtime .Machine ;
8- import com .dylibso .chicory .wasi .WasiOptions ;
9- import com .dylibso .chicory .wasm .WasmModule ;
10- import io .roastedroot .proxywasm .internal .ProxyWasm ;
11- import java .net .URI ;
12- import java .util .HashMap ;
13- import java .util .Map ;
14- import java .util .function .Function ;
15-
163/**
174 * Represents a Proxy-WASM plugin, providing the bridge between the host
185 * environment and the WASM module.
196 *
20- * <p>Concrete Plugin instances are created using the {@link Builder }.
7+ * <p>Concrete Plugin instances are created using a {@link PluginFactory }.
218 * The actual WASM instance and interaction logic are managed internally.
229 */
2310public interface Plugin {
@@ -28,333 +15,4 @@ public interface Plugin {
2815 * @return the plugin name, which might be null if not explicitly set via the builder.
2916 */
3017 String name ();
31-
32- /**
33- * Creates a new {@link Builder} to configure and construct a {@link Plugin} instance
34- * from the given WASM module.
35- *
36- * @param module the compiled {@link WasmModule} representing the plugin's code.
37- * @return a new {@link Plugin.Builder} instance.
38- */
39- static Plugin .Builder builder (WasmModule module ) {
40- return new Plugin .Builder (module );
41- }
42-
43- /**
44- * Builder for creating a Plugin instance.
45- */
46- final class Builder {
47-
48- private final WasmModule module ;
49- private final ProxyWasm .Builder proxyWasmBuilder = ProxyWasm .builder ().withStart (false );
50- private boolean shared ;
51- private String name ;
52- private HashMap <String , ForeignFunction > foreignFunctions ;
53- private HashMap <String , URI > upstreams ;
54- private boolean strictUpstreams ;
55- private int minTickPeriodMilliseconds ;
56- private LogHandler logger ;
57- private byte [] vmConfig ;
58- private byte [] pluginConfig ;
59- private MetricsHandler metricsHandler ;
60- private SharedQueueHandler sharedQueueHandler ;
61- private SharedDataHandler sharedDataHandler ;
62-
63- /**
64- * Private constructor for the Builder.
65- * Initializes the builder with the essential WASM module.
66- *
67- * @param module The compiled {@link WasmModule} containing the plugin code.
68- */
69- private Builder (WasmModule module ) {
70- this .module = module ;
71- }
72-
73- /**
74- * Sets the optional name for this plugin instance.
75- * This name can be used for identification and logging purposes.
76- *
77- * @param name the desired name for the plugin.
78- * @return this {@code Builder} instance for method chaining.
79- */
80- public Builder withName (String name ) {
81- this .name = name ;
82- return this ;
83- }
84-
85- /**
86- * Registers foreign (host-provided) functions that can be called by the WASM plugin.
87- * These functions allow the plugin to interact with the host environment beyond the standard
88- * Proxy-WASM ABI calls.
89- *
90- * @param functions A map where keys are the function names expected by the WASM module,
91- * and values are {@link ForeignFunction} implementations provided by the host.
92- * @return this {@code Builder} instance for method chaining.
93- * @see ForeignFunction
94- */
95- public Builder withForeignFunctions (Map <String , ForeignFunction > functions ) {
96- this .foreignFunctions = new HashMap <>(functions );
97- return this ;
98- }
99-
100- /**
101- * Defines mappings from logical upstream names (used within the plugin) to actual network URIs.
102- * This allows the plugin to make network calls (e.g., HTTP, gRPC) to services known by name,
103- * without needing to hardcode addresses.
104- *
105- * @param upstreams A map where keys are the logical upstream names used by the plugin,
106- * and values are the corresponding {@link URI}s of the target services.
107- * @return this {@code Builder} instance for method chaining.
108- */
109- public Builder withUpstreams (Map <String , URI > upstreams ) {
110- this .upstreams = new HashMap <>(upstreams );
111- return this ;
112- }
113-
114- /**
115- * Configures the behavior when a plugin attempts to call an upstream that is not defined
116- * in the `upstreams` map provided via {@link #withUpstreams(Map)}.
117- *
118- * <p>If {@code strictUpstreams} is {@code true}, attempting to use an undefined upstream name
119- * will result in an error being reported back to the plugin.
120- *
121- * <p>If {@code strictUpstreams} is {@code false} (the default behavior if this method is not called),
122- * the host will try to parse the upstream name as URI.
123- *
124- * @param strictUpstreams {@code true} to enforce that all used upstream names must be explicitly mapped,
125- * {@code false} to allow fallback resolution.
126- * @return this {@code Builder} instance for method chaining.
127- */
128- public Builder withStrictUpstreams (boolean strictUpstreams ) {
129- this .strictUpstreams = strictUpstreams ;
130- return this ;
131- }
132-
133- /**
134- * Sets a minimum interval for the plugin's periodic timer ticks ({@code proxy_on_tick}).
135- * The Proxy-WASM ABI allows plugins to request a timer tick period. This setting enforces
136- * a lower bound on that period to prevent plugins from requesting excessively frequent ticks,
137- * which could overload the host.
138- *
139- * <p>If the plugin requests a tick period shorter than this minimum, the host will use
140- * this minimum value instead.
141- *
142- * @param minTickPeriodMilliseconds the minimum allowed tick period in milliseconds. A value of 0 or less
143- * implies no minimum enforcement (host default behavior).
144- * @return this {@code Builder} instance for method chaining.
145- */
146- public Builder withMinTickPeriodMilliseconds (int minTickPeriodMilliseconds ) {
147- this .minTickPeriodMilliseconds = minTickPeriodMilliseconds ;
148- return this ;
149- }
150-
151- /**
152- * Provides a {@link LogHandler} implementation for the plugin to use.
153- * This handler receives log messages generated by the WASM module via the {@code proxy_log} ABI call.
154- * If no logger is provided, {@link LogHandler#DEFAULT} (a no-op logger) is used.
155- *
156- * @param logger the {@link LogHandler} implementation to handle plugin logs.
157- * @return this {@code Builder} instance for method chaining.
158- * @see LogHandler
159- */
160- public Builder withLogger (LogHandler logger ) {
161- this .logger = logger ;
162- return this ;
163- }
164-
165- /**
166- * Provides a {@link MetricsHandler} implementation for the plugin to use.
167- * This handler manages metric definition, recording, and retrieval requested by the WASM module
168- * via the relevant {@code proxy_*} ABI calls (e.g., {@code proxy_define_metric}).
169- * If no handler is provided, {@link MetricsHandler#DEFAULT} (which returns UNIMPLEMENTED)
170- * might be used implicitly.
171- *
172- * @param metricsHandler the {@link MetricsHandler} implementation to manage plugin metrics.
173- * @return this {@code Builder} instance for method chaining.
174- * @see MetricsHandler
175- */
176- public Builder withMetricsHandler (MetricsHandler metricsHandler ) {
177- this .metricsHandler = metricsHandler ;
178- return this ;
179- }
180-
181- /**
182- * Provides a {@link SharedQueueHandler} implementation for the plugin to use.
183- * This handler manages operations on shared message queues requested by the WASM module
184- * via the relevant {@code proxy_*} ABI calls (e.g., {@code proxy_register_shared_queue}).
185- * If no handler is provided, {@link SharedQueueHandler#DEFAULT} (which returns UNIMPLEMENTED)
186- * might be used implicitly.
187- *
188- * @param sharedQueueHandler the {@link SharedQueueHandler} implementation to manage shared queues.
189- * @return this {@code Builder} instance for method chaining.
190- * @see SharedQueueHandler
191- */
192- public Builder withSharedQueueHandler (SharedQueueHandler sharedQueueHandler ) {
193- this .sharedQueueHandler = sharedQueueHandler ;
194- return this ;
195- }
196-
197- /**
198- * Provides a {@link SharedDataHandler} implementation for the plugin to use.
199- * This handler manages operations on shared key-value data requested by the WASM module
200- * via the relevant {@code proxy_*} ABI calls (e.g., {@code proxy_get_shared_data}).
201- * If no handler is provided, {@link SharedDataHandler#DEFAULT} (which returns UNIMPLEMENTED)
202- * might be used implicitly.
203- *
204- * @param sharedDataHandler the {@link SharedDataHandler} implementation to manage shared data.
205- * @return this {@code Builder} instance for method chaining.
206- * @see SharedDataHandler
207- */
208- public Builder withSharedDataHandler (SharedDataHandler sharedDataHandler ) {
209- this .sharedDataHandler = sharedDataHandler ;
210- return this ;
211- }
212-
213- /**
214- * Configures whether the plugin instance should be shared across multiple host requests or contexts.
215- *
216- * <p>If {@code shared} is {@code true}, a single WASM instance will be created and reused.
217- * across multiple concurrent requests. Since Proxy-Wasm plugins are not thread-safe, the requests will
218- * contend on an access lock for the plugin. Using a shared plugin allows the plugin to maintain state
219- * between the requests. It will use less memory but will have a performance impact due to the contention.
220- *
221- * <p>If {@code shared} is {@code false} (the default), the host will create a new, separate WASM instance for each
222- * request or context (depending on the host implementation and threading model). This provides better
223- * isolation, eliminates contention, but consumes more memory.
224- *
225- * @param shared {@code true} to indicate the plugin instance can be shared, {@code false} otherwise.
226- * @return this {@code Builder} instance for method chaining.
227- */
228- public Builder withShared (boolean shared ) {
229- this .shared = shared ;
230- return this ;
231- }
232-
233- /**
234- * Sets the Virtual Machine (VM) configuration data for the plugin.
235- * This configuration is typically provided once when the VM (and the plugin) is initialized.
236- * It's accessible to the plugin via the {@code proxy_get_vm_configuration} ABI call.
237- *
238- * @param vmConfig A byte array containing the VM configuration data.
239- * @return this {@code Builder} instance for method chaining.
240- */
241- public Builder withVmConfig (byte [] vmConfig ) {
242- this .vmConfig = vmConfig ;
243- return this ;
244- }
245-
246- /**
247- * Sets the Virtual Machine (VM) configuration data for the plugin using a String.
248- * The string will be converted to bytes using the platform's default charset.
249- * This configuration is accessible via the {@code proxy_get_vm_configuration} ABI call.
250- *
251- * @param vmConfig A String containing the VM configuration data.
252- * @return this {@code Builder} instance for method chaining.
253- * @see #withVmConfig(byte[])
254- */
255- public Builder withVmConfig (String vmConfig ) {
256- this .vmConfig = bytes (vmConfig );
257- return this ;
258- }
259-
260- /**
261- * Sets the specific configuration data for this plugin instance.
262- * This configuration is provided during the plugin's initialization phase
263- * (via {@code proxy_on_configure}) and allows tailoring the plugin's behavior.
264- * It's accessible to the plugin via the {@code proxy_get_plugin_configuration} ABI call.
265- *
266- * @param pluginConfig A byte array containing the plugin-specific configuration data.
267- * @return this {@code Builder} instance for method chaining.
268- */
269- public Builder withPluginConfig (byte [] pluginConfig ) {
270- this .pluginConfig = pluginConfig ;
271- return this ;
272- }
273-
274- /**
275- * Sets the specific configuration data for this plugin instance using a String.
276- * The string will be converted to bytes using the platform's default charset.
277- * This configuration is accessible via the {@code proxy_get_plugin_configuration} ABI call.
278- *
279- * @param pluginConfig A String containing the plugin-specific configuration data.
280- * @return this {@code Builder} instance for method chaining.
281- * @see #withPluginConfig(byte[])
282- */
283- public Builder withPluginConfig (String pluginConfig ) {
284- this .pluginConfig = bytes (pluginConfig );
285- return this ;
286- }
287-
288- /**
289- * Provides an explicit memory instance to be used by the WASM module.
290- *
291- * @param memory The {@link ImportMemory} instance to be used by the WASM module.
292- * @return this {@code Builder} instance for method chaining.
293- */
294- public Builder withImportMemory (ImportMemory memory ) {
295- proxyWasmBuilder .withImportMemory (memory );
296- return this ;
297- }
298-
299- /**
300- * Configures a custom factory for creating the {@link Machine} used to execute the WASM code.
301- * The {@link Machine} controls the low-level execution of WASM instructions.
302- * By default, an interpreter-based machine is used.
303- * Providing a custom factory allows using alternative execution strategies, such as
304- * wasm to bytecode compilation to improve execution performance.
305- *
306- * <p>See the Chicory documentation (https://chicory.dev/docs/usage/runtime-compiler) for more details
307- * on WASM to bytecode compilation and execution.
308- *
309- * @param machineFactory A function that takes a WASM {@link Instance} and returns a {@link Machine}.
310- * @return this {@code Builder} instance for method chaining.
311- */
312- public Builder withMachineFactory (Function <Instance , Machine > machineFactory ) {
313- proxyWasmBuilder .withMachineFactory (machineFactory );
314- return this ;
315- }
316-
317- /**
318- * Configures WebAssembly System Interface (WASI) options for the plugin instance.
319- * WASI provides a standard interface for WASM modules to interact with the underlying operating system
320- * for tasks like file system access, environment variables, etc. While Proxy-WASM defines its own ABI,
321- * some modules might also utilize WASI features.
322- *
323- * @param options The {@link WasiOptions} to configure for the WASI environment.
324- * @return this {@code Builder} instance for method chaining.
325- */
326- public Builder withWasiOptions (WasiOptions options ) {
327- proxyWasmBuilder .withWasiOptions (options );
328- return this ;
329- }
330-
331- /**
332- * Constructs and initializes the {@link Plugin} instance based on the configuration
333- * provided to this builder.
334- *
335- * <p>This involves setting up the WASM environment, linking host functions, applying configurations,
336- * and calling the necessary Proxy-WASM lifecycle functions (like {@code _start} and
337- * {@code proxy_on_vm_start}).
338- *
339- * @return The fully configured and initialized {@link Plugin} instance.
340- * @throws StartException If any error occurs during the plugin initialization process
341- * (e.g., WASM instantiation failure, error during {@code proxy_on_vm_start}).
342- */
343- public Plugin build () throws StartException {
344- return new io .roastedroot .proxywasm .internal .Plugin (
345- proxyWasmBuilder .build (module ),
346- shared ,
347- name ,
348- foreignFunctions ,
349- upstreams ,
350- strictUpstreams ,
351- minTickPeriodMilliseconds ,
352- logger ,
353- vmConfig ,
354- pluginConfig ,
355- metricsHandler ,
356- sharedQueueHandler ,
357- sharedDataHandler );
358- }
359- }
36018}
0 commit comments