Skip to content

feat(core): implement service for Mini Moka #2537

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ OPENDAL_SFTP_KNOWN_HOSTS_STRATEGY=<accept|add|strict>
OPENDAL_SLED_TEST=false
OPENDAL_SLED_DATADIR=/path/to/database
OPENDAL_SLED_TREE=sled-tree
# mini-moka
OPENDAL_MINI_MOKA_TEST=false
# moka
OPENDAL_MOKA_TEST=false
# ghac
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ flamegraph.svg
perf.*

**/.DS_Store

# Yarn Integrity file
.yarn-integrity
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ Major components of the project include:

- ghac: [Github Action Cache](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows) Service
- memcached: [Memcached](https://memcached.org/) service
- moka: [moka](https://github.com/moka-rs/moka) backend
- mini_moka: [Mini Moka](https://github.com/moka-rs/mini-moka) backend
- moka: [Moka](https://github.com/moka-rs/moka) backend
- vercel_artifacts: [Vercel Remote Caching](https://vercel.com/docs/concepts/monorepos/remote-caching) Service *being worked on*

</details>
Expand Down
2 changes: 2 additions & 0 deletions bin/oli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ services-hdfs = ["opendal/services-hdfs"]
services-ipfs = ["opendal/services-ipfs"]
# Enable services memcached support
services-memcached = ["opendal/services-memcached"]
# Enable services mini-moka support
services-mini-moka = ["opendal/services-mini-moka"]
# Enable services moka support
services-moka = ["opendal/services-moka"]
# Enable services redis support
Expand Down
6 changes: 6 additions & 0 deletions bin/oli/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ impl Config {
path,
)),
// ignore the memory backend
#[cfg(feature = "services-mini-moka")]
Scheme::MiniMoka => Ok((
Operator::from_map::<services::MiniMoka>(profile.clone())?.finish(),
path,
)),
// ignore the memory backend
#[cfg(feature = "services-moka")]
Scheme::Moka => Ok((
Operator::from_map::<services::Moka>(profile.clone())?.finish(),
Expand Down
2 changes: 2 additions & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ services-ipfs = ["dep:prost"]
services-ipmfs = []
services-memcached = ["dep:bb8"]
services-memory = []
services-mini-moka = ["dep:mini-moka"]
services-moka = ["dep:moka"]
services-obs = [
"dep:reqsign",
Expand Down Expand Up @@ -194,6 +195,7 @@ madsim = { version = "0.2.21", optional = true }
md-5 = "0.10"
metrics = { version = "0.20", optional = true }
minitrace = { version = "0.4.0", optional = true }
mini-moka = { version = "0.10", optional = true }
moka = { version = "0.10", optional = true, features = ["future"] }
once_cell = "1"
openssh = { version = "0.9.9", optional = true }
Expand Down
1 change: 1 addition & 0 deletions core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
- [ipmfs](https://docs.rs/opendal/latest/opendal/services/struct.Ipmfs.html): [InterPlanetary File System](https://ipfs.tech/) MFS API support.
- [memcached](https://docs.rs/opendal/latest/opendal/services/struct.Memcached.html): [Memcached](https://memcached.org/) service support.
- [memory](https://docs.rs/opendal/latest/opendal/services/struct.Memory.html): In memory backend.
- [mini_moka](https://docs.rs/opendal/latest/opendal/services/struct.MiniMoka.html): [mini-moka](https://github.com/moka-rs/mini-moka) backend support.
- [moka](https://docs.rs/opendal/latest/opendal/services/struct.Moka.html): [moka](https://github.com/moka-rs/moka) backend support.
- [obs](https://docs.rs/opendal/latest/opendal/services/struct.Obs.html): [Huawei Cloud Object Storage](https://www.huaweicloud.com/intl/en-us/product/obs.html) Service (OBS).
- [oss](https://docs.rs/opendal/latest/opendal/services/struct.Oss.html): [Aliyun Object Storage Service](https://www.aliyun.com/product/oss) (OSS).
Expand Down
2 changes: 2 additions & 0 deletions core/benches/ops/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub fn services() -> Vec<(&'static str, Option<Operator>)> {
("fs", service::<services::Fs>()),
("s3", service::<services::S3>()),
("memory", service::<services::Memory>()),
#[cfg(feature = "services-mini-moka")]
("mini-moka", service::<services::MiniMoka>()),
#[cfg(feature = "services-moka")]
("moka", service::<services::Moka>()),
#[cfg(feature = "services-redis")]
Expand Down
1 change: 1 addition & 0 deletions core/src/docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- `services-ftp`: Enable ftp service support.
- `services-hdfs`: Enable hdfs service support.
- `services-memcached`: Enable memcached service support.
- `services-mini-moka`: Enable mini-moka service support.
- `services-moka`: Enable moka service support.
- `services-ipfs`: Enable ipfs service support.
- `services-redis`: Enable redis service support.
Expand Down
205 changes: 205 additions & 0 deletions core/src/services/mini_moka/backend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
// 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.

use std::collections::HashMap;
use std::fmt::Debug;
use std::time::Duration;

use async_trait::async_trait;
use log::debug;
use mini_moka::sync::Cache;
use mini_moka::sync::CacheBuilder;

use crate::raw::adapters::typed_kv;
use crate::*;

/// [mini-moka](https://github.com/moka-rs/mini-moka) backend support.
///
/// # Capabilities
///
/// This service can be used to:
///
/// - [x] stat
/// - [x] read
/// - [x] write
/// - [x] create_dir
/// - [x] delete
/// - [ ] copy
/// - [ ] rename
/// - [ ] list
/// - [ ] ~~scan~~
/// - [ ] presign
/// - [ ] blocking
///
/// # Notes
///
/// To better assist you in choosing the right cache for your use case,
/// Here's a comparison table with [moka](https://github.com/moka-rs/moka#choosing-the-right-cache-for-your-use-case)
#[derive(Default, Debug)]
pub struct MiniMokaBuilder {
/// Sets the max capacity of the cache.
///
/// Refer to [`mini-moka::sync::CacheBuilder::max_capacity`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.max_capacity)
max_capacity: Option<u64>,
/// Sets the time to live of the cache.
///
/// Refer to [`mini-moka::sync::CacheBuilder::time_to_live`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.time_to_live)
time_to_live: Option<Duration>,
/// Sets the time to idle of the cache.
///
/// Refer to [`mini-moka::sync::CacheBuilder::time_to_idle`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.time_to_idle)
time_to_idle: Option<Duration>,
}

impl MiniMokaBuilder {
/// Sets the max capacity of the cache.
///
/// Refer to [`mini-moka::sync::CacheBuilder::max_capacity`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.max_capacity)
pub fn max_capacity(&mut self, v: u64) -> &mut Self {
if v != 0 {
self.max_capacity = Some(v);
}
self
}

/// Sets the time to live of the cache.
///
/// Refer to [`mini-moka::sync::CacheBuilder::time_to_live`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.time_to_live)
pub fn time_to_live(&mut self, v: Duration) -> &mut Self {
if !v.is_zero() {
self.time_to_live = Some(v);
}
self
}

/// Sets the time to idle of the cache.
///
/// Refer to [`mini-moka::sync::CacheBuilder::time_to_idle`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.time_to_idle)
pub fn time_to_idle(&mut self, v: Duration) -> &mut Self {
if !v.is_zero() {
self.time_to_idle = Some(v);
}
self
}
}

impl Builder for MiniMokaBuilder {
const SCHEME: Scheme = Scheme::MiniMoka;
type Accessor = MiniMokaBackend;

fn from_map(map: HashMap<String, String>) -> Self {
let mut builder = MiniMokaBuilder::default();

map.get("max_capacity")
.map(|v| v.parse::<u64>().map(|v| builder.max_capacity(v)));
map.get("time_to_live").map(|v| {
v.parse::<u64>()
.map(|v| builder.time_to_live(Duration::from_secs(v)))
});
map.get("time_to_idle").map(|v| {
v.parse::<u64>()
.map(|v| builder.time_to_idle(Duration::from_secs(v)))
});
builder
}

fn build(&mut self) -> Result<Self::Accessor> {
debug!("backend build started: {:?}", &self);

let mut builder: CacheBuilder<String, typed_kv::Value, _> = Cache::builder();
// Use entries' bytes as capacity weigher.
builder = builder.weigher(|k, v| (k.len() + v.size()) as u32);
if let Some(v) = self.max_capacity {
builder = builder.max_capacity(v)
}
if let Some(v) = self.time_to_live {
builder = builder.time_to_live(v)
}
if let Some(v) = self.time_to_idle {
builder = builder.time_to_idle(v)
}

debug!("backend build finished: {:?}", &self);
Ok(MiniMokaBackend::new(Adapter {
inner: builder.build(),
}))
}
}

/// Backend is used to serve `Accessor` support in mini-moka.
pub type MiniMokaBackend = typed_kv::Backend<Adapter>;

#[derive(Clone)]
pub struct Adapter {
inner: Cache<String, typed_kv::Value>,
}

impl Debug for Adapter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Adapter")
.field("size", &self.inner.weighted_size())
.field("count", &self.inner.entry_count())
.finish()
}
}

#[async_trait]
impl typed_kv::Adapter for Adapter {
fn info(&self) -> typed_kv::Info {
typed_kv::Info::new(
Scheme::MiniMoka,
"mini-moka",
typed_kv::Capability {
get: true,
set: true,
delete: true,
..Default::default()
},
)
}

async fn get(&self, path: &str) -> Result<Option<typed_kv::Value>> {
self.blocking_get(path)
}

fn blocking_get(&self, path: &str) -> Result<Option<typed_kv::Value>> {
match self.inner.get(&path.to_string()) {
None => Ok(None),
Some(bs) => Ok(Some(bs)),
}
}

async fn set(&self, path: &str, value: typed_kv::Value) -> Result<()> {
self.blocking_set(path, value)
}

fn blocking_set(&self, path: &str, value: typed_kv::Value) -> Result<()> {
self.inner.insert(path.to_string(), value);

Ok(())
}

async fn delete(&self, path: &str) -> Result<()> {
self.blocking_delete(path)
}

fn blocking_delete(&self, path: &str) -> Result<()> {
self.inner.invalidate(&path.to_string());

Ok(())
}
}
19 changes: 19 additions & 0 deletions core/src/services/mini_moka/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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.

mod backend;
pub use backend::MiniMokaBuilder as MiniMoka;
5 changes: 5 additions & 0 deletions core/src/services/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ mod memory;
#[cfg(feature = "services-memory")]
pub use memory::Memory;

#[cfg(feature = "services-mini-moka")]
mod mini_moka;
#[cfg(feature = "services-mini-moka")]
pub use self::mini_moka::MiniMoka;

#[cfg(feature = "services-moka")]
mod moka;
#[cfg(feature = "services-moka")]
Expand Down
2 changes: 2 additions & 0 deletions core/src/types/operator/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ impl Operator {
Scheme::Memcached => Self::from_map::<services::Memcached>(map)?.finish(),
#[cfg(feature = "services-memory")]
Scheme::Memory => Self::from_map::<services::Memory>(map)?.finish(),
#[cfg(feature = "services-mini-moka")]
Scheme::MiniMoka => Self::from_map::<services::MiniMoka>(map)?.finish(),
#[cfg(feature = "services-moka")]
Scheme::Moka => Self::from_map::<services::Moka>(map)?.finish(),
#[cfg(feature = "services-obs")]
Expand Down
4 changes: 4 additions & 0 deletions core/src/types/scheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ pub enum Scheme {
Memcached,
/// [memory][crate::services::Memory]: In memory backend support.
Memory,
/// [mini-moka][crate::services::MiniMoka]: Mini Moka backend support.
MiniMoka,
/// [moka][crate::services::Moka]: moka backend support.
Moka,
/// [obs][crate::services::Obs]: Huawei Cloud OBS services.
Expand Down Expand Up @@ -142,6 +144,7 @@ impl FromStr for Scheme {
"ipmfs" => Ok(Scheme::Ipmfs),
"memcached" => Ok(Scheme::Memcached),
"memory" => Ok(Scheme::Memory),
"mini_moka" => Ok(Scheme::MiniMoka),
"moka" => Ok(Scheme::Moka),
"obs" => Ok(Scheme::Obs),
"redis" => Ok(Scheme::Redis),
Expand Down Expand Up @@ -176,6 +179,7 @@ impl From<Scheme> for &'static str {
Scheme::Ipmfs => "ipmfs",
Scheme::Memcached => "memcached",
Scheme::Memory => "memory",
Scheme::MiniMoka => "mini_moka",
Scheme::Moka => "moka",
Scheme::Obs => "obs",
Scheme::Onedrive => "onedrive",
Expand Down
2 changes: 2 additions & 0 deletions core/tests/behavior/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ fn main() -> anyhow::Result<()> {
tests.extend(behavior_test::<services::Memcached>());
#[cfg(feature = "services-memory")]
tests.extend(behavior_test::<services::Memory>());
#[cfg(feature = "services-mini-moka")]
tests.extend(behavior_test::<services::MiniMoka>());
#[cfg(feature = "services-moka")]
tests.extend(behavior_test::<services::Moka>());
#[cfg(feature = "services-obs")]
Expand Down
Loading