Map
SmartModule Maps are used to transform or edit each Record in a stream. We say that these SmartModules "map" each input record into a new output record by applying a function to the input data. This type of SmartModule may be used for many use-cases, such as:
- Narrowing large records into a smaller subset of important fields
- Scrubbing sensitive fields of data to be invisible to downstream consumers
- Computing rich, derived fields from simple raw data
Let's create a brand-new SmartModule Map to see what a minimal working example looks like.
Create a SmartModule Projectโ
Run smdk generate
with the name of the map and choose the "map" options:
$ smdk generate map-example
Generating new SmartModule project: map-example
project-group => 'john'
fluvio-smartmodule-cargo-dependency => '"0.2.5"'
๐ง Destination: ~/smdk/map-example ...
๐ง Generating template ...
โ ๐คท Will your SmartModule use init parameters? ยท false
โ ๐คท Which type of SmartModule would you like? ยท map
โ ๐คท Will your SmartModule be public? ยท false
Ignoring: /var/folders/5q/jwc86771549058kmbkbqjcdc0000gn/T/.tmpNFObJj/cargo-generate.toml
[1/5] Done: Cargo.toml
[2/5] Done: README.md
[3/5] Done: SmartModule.toml
[4/5] Done: src/lib.rs
[5/5] Done: src
๐ง Moving generated files into: `~/smdk/map-example`...
๐ก Initializing a fresh Git repository
โจ Done! New project created ~/smdk/map-example
We should see a new folder has been created for our project map-example
. Let's navigate inside and take a look at the sample Map generated for us by the template:
$ cd map-example && cat ./src/lib.rs
use fluvio_smartmodule::{smartmodule, Result, SmartModuleRecord, RecordData};
#[smartmodule(map)]
pub fn map(record: &SmartModuleRecord) -> Result<(Option<RecordData>, RecordData)> {
let key = record.key.clone();
let string = std::str::from_utf8(record.value.as_ref())?;
let int = string.parse::<i32>()?;
let value = (int * 2).to_string();
Ok((key, value.into()))
}
Let's break down what's happening here:
- Firstly,
#[smartmodule(map)]
marks the entry point for this SmartModule Map. There may only be one of these in the project, and it is called once for each record in the data stream. - The annotated function
fn map
may be named anything, but it must take a single&Record
argument. This variable contains the contents of one record in the stream, and you may read the Key and Value of this record as bytes. - The
fn map
function must return a new Key and Value for the output record. The Key is theOption<RecordData>
and the Value is theRecordData
in the return type.RecordData
is a helper type that may be constructed from any type that hasimpl Into<Vec<u8>>
such asString
, by using.into()
. - At any point in the SmartModule, errors may be returned using
?
or viaErr(e.into())
. This works for any error type that hasimpl std::error::Error
.
This template SmartModule will parse each record as an i32
integer, then multiply that value by 2.
Let's make sure our code compiles. If eveything works as expected, there will be a .wasm
file generated in the target directory.
$ smdk build
...
Compiling map-example v0.1.0 (~/smdk/map-example)
Finished release-lto [optimized] target(s) in1 12.83s
Your WASM binary is now ready for use.
Test with SMDKโ
Now that we've written our map, let's test using the command line.
$ smdk test --text=6
loading module at: ~/smdk/map-example/target/wasm32-unknown-unknown/release-lto/map_example.wasm
1 records outputed
12
Good news! ๐ it works as expected!