Skip to content

Commit 6e40c0a

Browse files
committed
Overall improvements and updates
1 parent f79436e commit 6e40c0a

File tree

7 files changed

+1027
-104
lines changed

7 files changed

+1027
-104
lines changed

.tool-versions

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
elixir 1.18.3-otp-27
2-
erlang 27.3.2
1+
elixir 1.19.4-otp-28
2+
erlang 28.2

README.md

Lines changed: 34 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@
55
[Cachex]: http://github.com/whitfin/cachex
66

77
![CI](http://github.com/elixir-nebulex/nebulex_adapters_cachex/workflows/CI/badge.svg)
8-
[![Codecov](http://codecov.io/gh/elixir-nebulex/nebulex_adapters_cachex/branch/v3.0.0-dev/graph/badge.svg)](http://codecov.io/gh/elixir-nebulex/nebulex_adapters_cachex/branch/v3.0.0-dev/graph/badge.svg)
8+
[![Codecov](http://codecov.io/gh/elixir-nebulex/nebulex_adapters_cachex/graph/badge.svg)](http://codecov.io/gh/elixir-nebulex/nebulex_adapters_cachex/branch/graph/badge.svg)
99
[![Hex Version](http://img.shields.io/hexpm/v/nebulex_adapters_cachex.svg)](http://hex.pm/packages/nebulex_adapters_cachex)
1010
[![Documentation](http://img.shields.io/badge/Documentation-ff69b4)](http://hexdocs.pm/nebulex_adapters_cachex)
1111

12+
## About
13+
14+
This adapter provides a Nebulex interface on top of [Cachex][Cachex], a powerful
15+
in-memory caching library for Elixir. It combines Nebulex's unified caching API
16+
with Cachex's rich feature set.
17+
1218
## Installation
1319

1420
Add `:nebulex_adapters_cachex` to your list of dependencies in `mix.exs`:
@@ -26,7 +32,7 @@ for more information.
2632

2733
## Usage
2834

29-
You can define a cache using Cachex as follows:
35+
Define your cache:
3036

3137
```elixir
3238
defmodule MyApp.Cache do
@@ -36,97 +42,64 @@ defmodule MyApp.Cache do
3642
end
3743
```
3844

39-
Where the configuration for the cache must be in your application
40-
environment, usually defined in your `config/config.exs`:
45+
Configure in your `config/config.exs`:
4146

4247
```elixir
4348
config :my_app, MyApp.Cache,
44-
stats: true,
45-
...
49+
stats: true
4650
```
4751

48-
If your application was generated with a supervisor (by passing `--sup`
49-
to `mix new`) you will have a `lib/my_app/application.ex` file containing
50-
the application start callback that defines and starts your supervisor.
51-
You just need to edit the `start/2` function to start the cache as a
52-
supervisor on your application's supervisor:
52+
Add to your application supervision tree:
5353

5454
```elixir
5555
def start(_type, _args) do
5656
children = [
5757
{MyApp.Cache, []},
58+
# ... other children
5859
]
5960

60-
...
61+
Supervisor.start_link(children, strategy: :one_for_one)
6162
end
6263
```
6364

64-
Since Cachex uses macros for some configuration options, you could also
65-
pass the options in runtime when the cache is started, either by calling
66-
`MyApp.Cache.start_link/1` directly, or in your app supervision tree:
65+
The adapter supports all Cachex options. See [Cachex.start_link/2][cachex_start_link]
66+
for configuration options including expiration, hooks, limits, and warmers.
6767

68-
```elixir
69-
def start(_type, _args) do
70-
children = [
71-
{MyApp.Cache, cachex_opts()},
72-
]
73-
74-
...
75-
end
76-
77-
defp cachex_opts do
78-
import Cachex.Spec
79-
80-
[
81-
expiration: expiration(
82-
# how often cleanup should occur
83-
interval: :timer.seconds(30),
84-
85-
# default record expiration
86-
default: :timer.seconds(60),
87-
88-
# whether to enable lazy checking
89-
lazy: true
90-
),
91-
92-
...
93-
]
94-
end
95-
```
96-
97-
> See [Cachex.start_link/2][cachex_start_link] for more information
98-
about the options.
68+
For more details and examples, see the [module documentation][docs].
9969

10070
[cachex_start_link]: http://hexdocs.pm/cachex/Cachex.html#start_link/2
71+
[docs]: http://hexdocs.pm/nebulex_adapters_cachex/Nebulex.Adapters.Cachex.html
72+
73+
## Distributed Caching Topologies
10174

102-
## Distributed caching topologies
75+
The Cachex adapter works seamlessly with Nebulex's distributed adapters. Use it
76+
as a local cache in multi-level topologies or as primary storage for partitioned
77+
caches.
10378

104-
Using the distributed adapters with `Cachex` as a primary storage is possible.
105-
For example, let's define a multi-level cache (near cache topology), where
106-
the L1 is a local cache using Cachex and the L2 is a partitioned cache.
79+
**Example: Multi-level cache (near cache pattern)**
10780

10881
```elixir
10982
defmodule MyApp.NearCache do
11083
use Nebulex.Cache,
111-
otp_app: :nebulex,
84+
otp_app: :my_app,
11285
adapter: Nebulex.Adapters.Multilevel
11386

11487
defmodule L1 do
11588
use Nebulex.Cache,
116-
otp_app: :nebulex,
89+
otp_app: :my_app,
11790
adapter: Nebulex.Adapters.Cachex
11891
end
11992

12093
defmodule L2 do
12194
use Nebulex.Cache,
122-
otp_app: :nebulex,
95+
otp_app: :my_app,
12396
adapter: Nebulex.Adapters.Partitioned,
12497
primary_storage_adapter: Nebulex.Adapters.Cachex
12598
end
12699
end
127100
```
128101

129-
And the configuration may look like:
102+
Configuration:
130103

131104
```elixir
132105
config :my_app, MyApp.NearCache,
@@ -137,16 +110,12 @@ config :my_app, MyApp.NearCache,
137110
]
138111
```
139112

140-
> **NOTE:** You could also use [Nebulex.Adapters.Redis][nbx_redis_adapter]
141-
> for L2, it would be matter of changing the adapter for the L2 and the
142-
> configuration for set up Redis adapter.
143-
144-
See [Nebulex examples](http://github.com/elixir-nebulex/nebulex_examples).
145-
You will find examples for all different topologies, even using other adapters
146-
like Redis; for all examples you just have to replace `Nebulex.Adapters.Local`
147-
by `Nebulex.Adapters.Cachex`.
113+
You can also use [Nebulex.Adapters.Redis][nbx_redis_adapter] for L2 to add
114+
persistence. See the [module documentation][docs] and
115+
[Nebulex examples][nbx_examples] for more topologies.
148116

149117
[nbx_redis_adapter]: http://github.com/elixir-nebulex/nebulex_redis_adapter
118+
[nbx_examples]: http://github.com/elixir-nebulex/nebulex_examples
150119

151120
## Testing
152121

@@ -161,7 +130,7 @@ to `nebulex`:
161130
export NEBULEX_PATH=nebulex
162131
```
163132

164-
Second, make sure you fetch `:nebulex` dependency directly from GtiHub
133+
Second, make sure you fetch `:nebulex` dependency directly from GitHub
165134
by running:
166135

167136
```
@@ -212,11 +181,11 @@ When submitting a pull request you should not update the
212181
[CHANGELOG.md](CHANGELOG.md), and also make sure you test your changes
213182
thoroughly, include unit tests alongside new or changed code.
214183

215-
Before to submit a PR it is highly recommended to run `mix test.ci` and ensure
184+
Before submitting a PR it is highly recommended to run `mix test.ci` and ensure
216185
all checks run successfully.
217186

218187
## Copyright and License
219188

220189
Copyright (c) 2020, Carlos Bolaños.
221190

222-
Nebulex.Adapters.Cachex source code is licensed under the [MIT License](LICENSE).
191+
Nebulex.Adapters.Cachex source code is licensed under the [MIT License](LICENSE.md).

lib/nebulex/adapters/cachex.ex

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@ defmodule Nebulex.Adapters.Cachex do
22
@moduledoc """
33
Nebulex adapter for [Cachex][cachex].
44
5+
This adapter provides a Nebulex interface on top of Cachex, a powerful
6+
in-memory caching library for Elixir. It combines Nebulex's unified caching
7+
API with Cachex's rich feature set including transactions, hooks, expiration,
8+
and statistics. Use this adapter when you need a feature-rich local cache or
9+
as a building block for distributed caching topologies.
10+
511
[cachex]: http://hexdocs.pm/cachex/Cachex.html
612
713
## Options
814
9-
Since Nebulex is just a wrapper on top of Cachex, the options are the same as
10-
[Cachex.start_link/2][cachex_start_link].
15+
This adapter supports all Cachex configuration options. The options are passed
16+
directly to [Cachex.start_link/2][cachex_start_link], allowing you to leverage
17+
Cachex's full feature set including expiration, hooks, limits, and warmers.
1118
1219
[cachex_start_link]: https://hexdocs.pm/cachex/Cachex.html#start_link/2
1320
@@ -115,15 +122,92 @@ defmodule Nebulex.Adapters.Cachex do
115122
]
116123
117124
> **NOTE:** You could also use [Nebulex.Adapters.Redis][nbx_redis_adapter] for
118-
L2, it would be matter of changing the adapter for the L2 and the
119-
configuration to set up Redis adapter.
125+
L2, it would be a matter of changing the adapter for the L2 and the
126+
configuration to set up the Redis adapter.
120127
121128
[nbx_redis_adapter]: https://github.com/elixir-nebulex/nebulex_redis_adapter
122129
123130
See [Nebulex examples](https://github.com/elixir-nebulex/nebulex_examples).
124131
You will find examples for all different topologies, even using other adapters
125132
like Redis; for all examples using the `Nebulex.Adapters.Local` adapter,
126133
you can replace it by `Nebulex.Adapters.Cachex`.
134+
135+
## Query API
136+
137+
The adapter supports querying cached entries using Cachex's query syntax or
138+
explicit key lists.
139+
140+
### Pattern-based queries
141+
142+
Use Cachex query syntax for pattern matching:
143+
144+
# Get all entries
145+
MyApp.Cache.get_all!()
146+
147+
# Count all entries
148+
MyApp.Cache.count_all!()
149+
150+
# Delete all entries
151+
MyApp.Cache.delete_all!()
152+
153+
# Delete expired entries
154+
MyApp.Cache.delete_all!(:expired)
155+
156+
# Stream entries for large datasets
157+
MyApp.Cache.stream!() |> Enum.take(100)
158+
159+
### Explicit key queries
160+
161+
Query specific keys using the `in: keys` syntax:
162+
163+
# Get multiple keys
164+
MyApp.Cache.get_all!(in: ["key1", "key2", "key3"])
165+
166+
# Count specific keys
167+
MyApp.Cache.count_all!(in: ["key1", "key2"])
168+
169+
# Delete specific keys
170+
MyApp.Cache.delete_all!(in: ["key1", "key2"])
171+
172+
## Transactions
173+
174+
The adapter provides full transaction support through Cachex's locking
175+
mechanism, ensuring atomic operations across multiple keys.
176+
177+
MyApp.Cache.transaction(
178+
fn ->
179+
value = MyApp.Cache.get!("counter")
180+
MyApp.Cache.put!("counter", value + 1)
181+
MyApp.Cache.put!("last_updated", DateTime.utc_now())
182+
end,
183+
keys: ["counter", "last_updated"]
184+
)
185+
186+
Transactions automatically handle locking and isolation for the specified keys.
187+
188+
## Stats and Monitoring
189+
190+
Enable statistics collection by setting `stats: true` in your configuration
191+
(enabled by default):
192+
193+
config :my_app, MyApp.Cache,
194+
stats: true
195+
196+
Retrieve statistics:
197+
198+
# Get all stats
199+
iex> MyApp.Cache.info!(:stats)
200+
%{
201+
calls: %{get: 10, put: 5, delete: 2},
202+
evictions: 0,
203+
expirations: 1,
204+
hit_rate: 80.0,
205+
hits: 8,
206+
misses: 2,
207+
...
208+
}
209+
210+
See `Cachex.Stats` for detailed statistics information.
127211
"""
128212

129213
# Provide Cache Implementation

mix.exs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,7 @@ defmodule NebulexAdaptersCachex.MixProject do
1616

1717
# Testing
1818
test_coverage: [tool: ExCoveralls],
19-
preferred_cli_env: [
20-
coveralls: :test,
21-
"coveralls.detail": :test,
22-
"coveralls.post": :test,
23-
"coveralls.html": :test,
24-
"test.ci": :test
25-
],
19+
test_ignore_filters: [~r{test/(shared|support)/.*\.exs}],
2620

2721
# Dialyzer
2822
dialyzer: dialyzer(),
@@ -40,6 +34,18 @@ defmodule NebulexAdaptersCachex.MixProject do
4034
]
4135
end
4236

37+
def cli do
38+
[
39+
preferred_envs: [
40+
coveralls: :test,
41+
"coveralls.detail": :test,
42+
"coveralls.post": :test,
43+
"coveralls.html": :test,
44+
"test.ci": :test
45+
]
46+
]
47+
end
48+
4349
defp deps do
4450
[
4551
nebulex_dep(),
@@ -50,16 +56,16 @@ defmodule NebulexAdaptersCachex.MixProject do
5056
{:excoveralls, "~> 0.18", only: :test},
5157
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
5258
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false},
53-
{:sobelow, "~> 0.13", only: [:dev, :test], runtime: false},
54-
{:mimic, "~> 1.7", only: :test},
55-
{:stream_data, "~> 1.1", only: [:dev, :test]},
59+
{:sobelow, "~> 0.14", only: [:dev, :test], runtime: false},
60+
{:mimic, "~> 2.2", only: :test},
61+
{:stream_data, "~> 1.2", only: [:dev, :test]},
5662

5763
# Benchmark Test
58-
{:benchee, "~> 1.3", only: [:dev, :test]},
64+
{:benchee, "~> 1.5", only: [:dev, :test]},
5965
{:benchee_html, "~> 1.0", only: [:dev, :test]},
6066

6167
# Docs
62-
{:ex_doc, "~> 0.36", only: [:dev, :test], runtime: false}
68+
{:ex_doc, "~> 0.39", only: [:dev, :test], runtime: false}
6369
]
6470
end
6571

0 commit comments

Comments
 (0)