Fastly Compute C++ SDK
Loading...
Searching...
No Matches
simple.h
Go to the documentation of this file.
1#ifndef FASTLY_CACHE_SIMPLE_H
2#define FASTLY_CACHE_SIMPLE_H
3
4#include <chrono>
5#include <fastly/cache/core.h>
6#include <fastly/expected.h>
7#include <fastly/http/body.h>
8#include <functional>
9#include <optional>
10#include <span>
11#include <string>
12#include <string_view>
13#include <type_traits>
14#include <vector>
15
19public:
38
39 CacheError(Code code) : code_(code) {}
40 Code code() const { return code_; }
41
42private:
43 Code code_;
44};
45
48public:
49 CacheEntry(http::Body val, std::chrono::nanoseconds ttl)
50 : value_(std::move(val)), ttl_(ttl) {}
51
52 http::Body &value() { return value_; }
53 const http::Body &value() const { return value_; }
54 std::chrono::nanoseconds ttl() const { return ttl_; }
55
56private:
58 http::Body value_;
60 std::chrono::nanoseconds ttl_;
61};
62
64class PurgeOptions {
65public:
66 enum Scope {
71 };
72
77 static PurgeOptions pop_scope() { return PurgeOptions(Scope::Pop); }
78
85 static PurgeOptions global_scope() { return PurgeOptions(Scope::Global); }
86
87 Scope scope() const { return scope_; }
88
89private:
90 explicit PurgeOptions(Scope s) : scope_(s) {}
91 Scope scope_;
92};
93
94namespace detail {
97std::string surrogate_key_for_cache_key(std::span<const std::uint8_t> key,
99
102} // namespace detail
103
113tl::expected<std::optional<http::Body>, CacheError>
114get(std::span<const std::uint8_t> key);
115
124inline tl::expected<std::optional<http::Body>, CacheError>
125get(std::string_view key) {
126 return get(std::span(reinterpret_cast<const std::uint8_t *>(key.data()),
127 key.size()));
128}
129
146tl::expected<http::Body, CacheError>
147get_or_set(std::span<const std::uint8_t> key, http::Body value,
148 std::chrono::nanoseconds ttl);
149
165inline tl::expected<http::Body, CacheError>
166get_or_set(std::string_view key, http::Body value,
167 std::chrono::nanoseconds ttl) {
168 return get_or_set(
169 std::span(reinterpret_cast<const std::uint8_t *>(key.data()), key.size()),
170 std::move(value), ttl);
171}
172
188template <class F>
189tl::expected<std::optional<http::Body>, CacheError>
190get_or_set_with(std::span<const std::uint8_t> key, F make_entry)
191 requires std::invocable<F> &&
192 std::same_as<std::invoke_result_t<F>, std::optional<CacheEntry>>
193{
194 auto lookup_result = core::Transaction::lookup(key).execute();
195 if (!lookup_result.has_value()) {
196 return tl::unexpected(detail::from_core_error(lookup_result.error()));
197 }
198
199 auto &lookup_tx = lookup_result.value();
200
201 if (!lookup_tx.must_insert_or_update()) {
202 if (auto found = lookup_tx.found()) {
203 auto stream_result = found->to_stream();
204 if (!stream_result.has_value()) {
205 return tl::unexpected(detail::from_core_error(stream_result.error()));
206 }
207 return std::optional<http::Body>(std::move(stream_result.value()));
208 } else {
209 return tl::unexpected(CacheError(CacheError::Code::InvalidOperation));
210 }
211 }
212
213 // Run the user-provided closure to produce the entry
214 auto entry = make_entry();
215 if (!entry.has_value()) {
216 return tl::unexpected(CacheError(CacheError::Code::GetOrSet));
217 }
218
219 // Create surrogate keys for both POP and global purging
220 std::vector<std::string> surrogate_keys = {
223 };
224
225 auto insert_result = std::move(lookup_tx)
226 .insert(entry->ttl())
227 .surrogate_keys(surrogate_keys)
228 .execute_and_stream_back();
229
230 if (!insert_result.has_value()) {
231 return tl::unexpected(detail::from_core_error(insert_result.error()));
232 }
233
234 auto [insert_body, found] = std::move(insert_result.value());
235
236 insert_body.append(std::move(entry->value()));
237 auto finish_result = insert_body.finish();
238 if (!finish_result.has_value()) {
239 return tl::unexpected(CacheError(CacheError::Code::Other));
240 }
241
242 auto stream_result = found.to_stream();
243 if (!stream_result.has_value()) {
244 return tl::unexpected(detail::from_core_error(stream_result.error()));
245 }
246
247 return std::optional<http::Body>(std::move(stream_result.value()));
248}
249
264template <class F>
265tl::expected<std::optional<http::Body>, CacheError>
266get_or_set_with(std::string_view key, F make_entry) {
267 return get_or_set_with(
268 std::span(reinterpret_cast<const std::uint8_t *>(key.data()), key.size()),
269 std::move(make_entry));
270}
271
285tl::expected<void, CacheError> purge(std::span<const std::uint8_t> key);
286
299inline tl::expected<void, CacheError> purge(std::string_view key) {
300 return purge(std::span(reinterpret_cast<const std::uint8_t *>(key.data()),
301 key.size()));
302}
303
325tl::expected<void, CacheError>
326purge_with_opts(std::span<const std::uint8_t> key, const PurgeOptions &opts);
327
347inline tl::expected<void, CacheError>
348purge_with_opts(std::string_view key, const PurgeOptions &opts) {
349 return purge_with_opts(
350 std::span(reinterpret_cast<const std::uint8_t *>(key.data()), key.size()),
351 opts);
352}
353
354} // namespace fastly::cache::simple
355
356#endif // FASTLY_CACHE_SIMPLE_H
Errors that can arise during cache operations.
Definition core.h:20
tl::expected< Transaction, CacheError > execute() &&
static TransactionLookupBuilder lookup(std::span< const std::uint8_t > key)
CacheEntry(http::Body val, std::chrono::nanoseconds ttl)
Definition simple.h:49
http::Body & value()
Definition simple.h:52
const http::Body & value() const
Definition simple.h:53
std::chrono::nanoseconds ttl() const
Definition simple.h:54
Errors arising from cache operations.
Definition simple.h:18
Code code() const
Definition simple.h:40
Code
Definition simple.h:20
@ GetOrSet
An error occurred while running the closure argument of get_or_set_with.
Definition simple.h:34
@ Purge
An error occurred when purging a value.
Definition simple.h:32
@ Other
An unknown error occurred.
Definition simple.h:36
@ LimitExceeded
Operation failed due to a limit.
Definition simple.h:22
@ Unsupported
Cache operation is not supported.
Definition simple.h:28
@ InvalidOperation
Definition simple.h:26
@ Io
An I/O error occurred.
Definition simple.h:30
CacheError(Code code)
Definition simple.h:39
Options for purge operations.
Definition simple.h:64
Scope scope() const
Definition simple.h:87
static PurgeOptions global_scope()
Definition simple.h:85
static PurgeOptions pop_scope()
Definition simple.h:77
@ Pop
Purge the key from the current POP (default behavior).
Definition simple.h:68
@ Global
Purge the key globally (requires additional Fastly configuration).
Definition simple.h:70
Definition body.h:49
Definition simple.h:94
fastly::cache::simple::CacheError from_core_error(const fastly::cache::core::CacheError &err)
std::string surrogate_key_for_cache_key(std::span< const std::uint8_t > key, PurgeOptions::Scope scope)
Definition simple.h:16
tl::expected< std::optional< http::Body >, CacheError > get_or_set_with(std::span< const std::uint8_t > key, F make_entry)
Definition simple.h:190
tl::expected< std::optional< http::Body >, CacheError > get(std::span< const std::uint8_t > key)
tl::expected< http::Body, CacheError > get_or_set(std::span< const std::uint8_t > key, http::Body value, std::chrono::nanoseconds ttl)
tl::expected< void, CacheError > purge_with_opts(std::span< const std::uint8_t > key, const PurgeOptions &opts)
tl::expected< void, CacheError > purge(std::span< const std::uint8_t > key)