Skip to content

Commit

Permalink
[ISSUE apache#4612] init shenyu-plugin-wasm-api module
Browse files Browse the repository at this point in the history
  • Loading branch information
loongs-zhang committed Jan 27, 2024
1 parent a026635 commit 254ea20
Show file tree
Hide file tree
Showing 17 changed files with 351 additions and 32 deletions.
1 change: 1 addition & 0 deletions shenyu-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

<modules>
<module>shenyu-plugin-api</module>
<module>shenyu-plugin-wasm-api</module>
<module>shenyu-plugin-base</module>
<module>shenyu-plugin-wasm-base</module>
<module>shenyu-plugin-httpclient</module>
Expand Down
49 changes: 49 additions & 0 deletions shenyu-plugin/shenyu-plugin-wasm-api/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.shenyu</groupId>
<artifactId>shenyu-plugin</artifactId>
<version>2.6.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shenyu-plugin-wasm-api</artifactId>

<dependencies>
<dependency>
<groupId>org.apache.shenyu</groupId>
<artifactId>shenyu-plugin-base</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.github.kawamuray.wasmtime</groupId>
<artifactId>wasmtime-java</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

package org.apache.shenyu.plugin.wasm.base;
package org.apache.shenyu.plugin.wasm.api;

import io.github.kawamuray.wasmtime.Extern;
import io.github.kawamuray.wasmtime.WasmFunctions;
Expand All @@ -25,6 +25,7 @@
import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
import org.apache.shenyu.plugin.api.result.ShenyuResultWrap;
import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
import org.apache.shenyu.plugin.wasm.api.loader.WasmLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
Expand All @@ -41,7 +42,7 @@
*
* @see org.apache.shenyu.plugin.api.ShenyuPlugin
* @see io.github.kawamuray.wasmtime.WasmValType
* @see org.apache.shenyu.plugin.wasm.base.WasmLoader
* @see WasmLoader
*/
public abstract class AbstractWasmPlugin extends WasmLoader implements ShenyuPlugin {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

package org.apache.shenyu.plugin.wasm.base.exception;
package org.apache.shenyu.plugin.wasm.api.exception;

import org.apache.shenyu.common.exception.ShenyuException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

package org.apache.shenyu.plugin.wasm.base.exception;
package org.apache.shenyu.plugin.wasm.api.exception;

/**
* Shenyu WASM init Exception.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

package org.apache.shenyu.plugin.wasm.base;
package org.apache.shenyu.plugin.wasm.api.loader;

import io.github.kawamuray.wasmtime.Extern;
import io.github.kawamuray.wasmtime.Func;
Expand All @@ -25,7 +25,7 @@
import io.github.kawamuray.wasmtime.Store;
import io.github.kawamuray.wasmtime.wasi.WasiCtx;
import io.github.kawamuray.wasmtime.wasi.WasiCtxBuilder;
import org.apache.shenyu.plugin.wasm.base.exception.ShenyuWasmInitException;
import org.apache.shenyu.plugin.wasm.api.exception.ShenyuWasmInitException;

import java.io.IOException;
import java.net.URISyntaxException;
Expand Down
19 changes: 19 additions & 0 deletions shenyu-plugin/shenyu-plugin-wasm-api/src/test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# How to build the wasm file

1. install rustup

2. install rust

3. generate the wasm file

```shell
cd {shenyu}/shenyu-plugin/shenyu-plugin-wasm-api/src/test/rust-wasm-filter
cargo build --target wasm32-wasi --release
```

then you will see the wasm file
in `{shenyu}/shenyu-plugin/shenyu-plugin-wasm-api/src/test/rust-wasm-filter/target/wasm32-wasi/release/rust_filter.wasm`

4. rename the wasm file

rename the file to `org.apache.shenyu.plugin.wasm.api.AbstractWasmPluginTest$RustWasmPlugin.wasm`
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

package org.apache.shenyu.plugin.wasm.base;
package org.apache.shenyu.plugin.wasm.api;

import io.github.kawamuray.wasmtime.Func;
import io.github.kawamuray.wasmtime.Store;
Expand Down
6 changes: 1 addition & 5 deletions shenyu-plugin/shenyu-plugin-wasm-base/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,9 @@
<dependencies>
<dependency>
<groupId>org.apache.shenyu</groupId>
<artifactId>shenyu-plugin-base</artifactId>
<artifactId>shenyu-plugin-wasm-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.github.kawamuray.wasmtime</groupId>
<artifactId>wasmtime-java</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.shenyu.plugin.api.result.ShenyuResultWrap;
import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
import org.apache.shenyu.plugin.wasm.api.loader.WasmLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
Expand All @@ -45,7 +46,7 @@
*
* @see org.apache.shenyu.plugin.base.AbstractShenyuPlugin
* @see io.github.kawamuray.wasmtime.WasmValType
* @see org.apache.shenyu.plugin.wasm.base.WasmLoader
* @see org.apache.shenyu.plugin.wasm.api.loader.WasmLoader
*/
public abstract class AbstractShenyuWasmPlugin extends AbstractShenyuPlugin {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.shenyu.plugin.wasm.base.handler;

import io.github.kawamuray.wasmtime.WasmFunctions;
import io.github.kawamuray.wasmtime.WasmValType;
import org.apache.shenyu.common.dto.DiscoverySyncData;
import org.apache.shenyu.plugin.base.handler.DiscoveryUpstreamDataHandler;
import org.apache.shenyu.plugin.wasm.api.exception.ShenyuWasmInitException;
import org.apache.shenyu.plugin.wasm.api.loader.WasmLoader;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* upstreamList data change.
*/
public abstract class AbstractWasmDiscoveryHandler extends WasmLoader implements DiscoveryUpstreamDataHandler {

protected static final Map<Long, DiscoverySyncData> ARGUMENTS = new ConcurrentHashMap<>();

protected static final String METHOD_NAME = "handlerDiscoveryUpstreamData";

@Override
public void handlerDiscoveryUpstreamData(final DiscoverySyncData discoverySyncData) {
super.getWasmExtern(METHOD_NAME)
.map(handlerDiscoveryUpstreamData -> {
// WASI cannot easily pass Java objects like JNI, here we pass Long as arg
// then we can get the argument by Long
final Long argumentId = getArgumentId(discoverySyncData);
ARGUMENTS.put(argumentId, discoverySyncData);
// call WASI function
WasmFunctions.consumer(super.getStore(), handlerDiscoveryUpstreamData.func(), WasmValType.I64)
.accept(argumentId);
ARGUMENTS.remove(argumentId);
return argumentId;
}).orElseThrow(() -> new ShenyuWasmInitException(METHOD_NAME + " function not find in wasm file: " + getWasmName()));
}

protected abstract Long getArgumentId(DiscoverySyncData discoverySyncData);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.shenyu.plugin.wasm.base.handler;

import io.github.kawamuray.wasmtime.Extern;
import io.github.kawamuray.wasmtime.WasmFunctions;
import io.github.kawamuray.wasmtime.WasmValType;
import org.apache.shenyu.common.dto.MetaData;
import org.apache.shenyu.plugin.base.handler.MetaDataHandler;
import org.apache.shenyu.plugin.wasm.api.exception.ShenyuWasmInitException;
import org.apache.shenyu.plugin.wasm.api.loader.WasmLoader;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* The type abstract wasm metadata subscriber.
*/
public abstract class AbstractWasmMetaDataHandler extends WasmLoader implements MetaDataHandler {

protected static final Map<Long, MetaData> ARGUMENTS = new ConcurrentHashMap<>();

protected static final String HANDLE_METHOD_NAME = "handle";

protected static final String REMOVE_METHOD_NAME = "remove";

protected static final String REFRESH_METHOD_NAME = "refresh";

@Override
public void handle(final MetaData metaData) {
super.getWasmExtern(HANDLE_METHOD_NAME)
.map(handle -> callWASI(metaData, handle))
.orElseThrow(() -> new ShenyuWasmInitException(HANDLE_METHOD_NAME + " function not find in wasm file: " + getWasmName()));
}

@Override
public void remove(final MetaData metaData) {
super.getWasmExtern(REMOVE_METHOD_NAME)
.map(remove -> callWASI(metaData, remove))
.orElseThrow(() -> new ShenyuWasmInitException(REMOVE_METHOD_NAME + " function not find in wasm file: " + getWasmName()));
}

private Long callWASI(final MetaData metaData, final Extern execute) {
// WASI cannot easily pass Java objects like JNI, here we pass Long as arg
// then we can get the argument by Long
final Long argumentId = getArgumentId(metaData);
ARGUMENTS.put(argumentId, metaData);
// call WASI function
WasmFunctions.consumer(super.getStore(), execute.func(), WasmValType.I64)
.accept(argumentId);
ARGUMENTS.remove(argumentId);
return argumentId;
}

protected abstract Long getArgumentId(MetaData metaData);

@Override
public void refresh() {
super.getWasmExtern(REFRESH_METHOD_NAME)
.ifPresent(refresh -> WasmFunctions.consumer(super.getStore(), refresh.func()).accept());
}
}
Loading

0 comments on commit 254ea20

Please sign in to comment.