Skip to content

Commit ccf6e40

Browse files
committed
breaking: Move the builder from the Plugin to the PluginFactory
• Plugins are now only created/started when they are first grabbed form the pool • Update test examples to use new PluginFactory.builder() API instead of Plugin.builder() • Switch from experimental AotMachine to MachineFactoryCompiler for bytecode compilation Signed-off-by: Hiram Chirino <hiram@hiramchirino.com>
1 parent 459475f commit ccf6e40

File tree

7 files changed

+466
-440
lines changed

7 files changed

+466
-440
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The Java host implementation for Proxy-Wasm, enabling developers to run Proxy-Wa
88

99
TODO: still need to document how to use in non-cdi containers.
1010

11-
If your using Quarkus, see the [Quarkus Proxy-Wasm Extension](https://github.com/roastedroot/quarkus-proxy-wasm) docs.
11+
If your using Quarkus, see the [Quarkus Proxy-Wasm Extension](https://docs.quarkiverse.io/quarkus-proxy-wasm/dev/index.html) docs.
1212

1313
## Building
1414

Lines changed: 1 addition & 343 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,10 @@
11
package 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
*/
2310
public 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

Comments
 (0)