1
1
package io .roastedroot .proxywasm ;
2
2
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
-
16
3
/**
17
4
* Represents a Proxy-WASM plugin, providing the bridge between the host
18
5
* environment and the WASM module.
19
6
*
20
- * <p>Concrete Plugin instances are created using the {@link Builder }.
7
+ * <p>Concrete Plugin instances are created using a {@link PluginFactory }.
21
8
* The actual WASM instance and interaction logic are managed internally.
22
9
*/
23
10
public interface Plugin {
@@ -28,333 +15,4 @@ public interface Plugin {
28
15
* @return the plugin name, which might be null if not explicitly set via the builder.
29
16
*/
30
17
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
- }
360
18
}
0 commit comments