SlideShare a Scribd company logo
1 of 53
Download to read offline
Writing modular &
encapsulated Redis code
Jim Nelson
jnelson@archive.org
Internet Archive
Internet Archive
Universal Access to All Knowledge
● Founded 1996, based in San Francisco
● Archive of digital and physical media
● Includes Web, books, music, film, software & more
● Digital holdings: over 35 petabytes & counting
● Over 1 million users per day
● Key collections & services:
○ Wayback Machine
○ Grateful Dead live concert collection
○ The Emularity: in-browser emulation of 8-bit software, IBM
PC, Mac, & now handhelds like Speak-and-Spell
Internet Archive ♡ Redis
● Caching & directory lookup backed by 10-node sharded Redis cluster
● Sharding performed client-side via consistent hashing (PHP, Predis)
● Each node supported by two replicated mirrors (fail-over)
● Specialized Redis instances also used throughout IA’s services, including
○ Wayback Machine
○ Search (item metadata and full-text)
○ Administrative & usage tracking
○ …and more
Before we get started
● I’m assuming you’ve written Redis client code already
● You don’t need to know the exact details of the Redis protocol…
● …but you need some understanding of how Redis “works”
○ single-threaded
○ different data types (strings, hash, sorted sets, etc.)
○ transactions (MULTI/EXEC)
This presentation uses PHP sample code and Predis (a PHP Redis client)
but most concepts presented should work in other languages & clients
Redis rocks…
“Baby, where have you been my whole life?”
● Quick, quick, quick
○ Quick to code
○ Quick to debug
○ Quick response times
○ Quick to model data
● Logical, well-defined command structure
● Atomicity
● Flexibility over rigor
Learning only a handful of straightforward concepts,
I felt I had a solid working understanding of Redis
…but there
are issues.
“It’s complicated.” (As in, Facebook-it’s-complicated.)
● Application code mixed with data model code
○ Little-to-no separation between data logic and business logic
● Relational data often sprayed across separate Redis buckets
○ No clean way to normalize or deserialize complex objects if they’re
sharded across keys
● Performance considerations trump clean coding practices
○ Modularity ignored in order to minimize round-trips to server
The temptation of Redis is
that it looks like a
collections framework.
What’s missing?
All the things I know and love about designing clean code.
Modularity
Encapsulation
Readability
What is
encapsulation?
Encapsulation “says that a program
should be divided into modules that
hide data structures behind an
interface of procedure calls. The
purpose of this is to allow you to
change the underlying data structure
without causing a large ripple effect
across the system.”
–Martin Fowler,
martinfowler.com
Redis programming today
Sending & receiving data
Redis (and most Redis clients) offer different modes of
operation:
● Immediate mode
● Pipeline mode
● Transaction mode
● Atomic pipeline mode
Immediate mode
Send one command, receive one response.
That’s it. No, really.
$redis = new PredisClient();
$name = $redis->get(“user:$id:name”); // sends GET, recvs name
$email = $redis->get(“user:$id:email”); // sends GET, recvs email
$login_count = $redis->incr(“user:$id:logins”) // sends INCR, recvs incremented number
Simple enough!
Pipeline mode
● Collect (or schedule) several commands on the client side
● Send all commands in one burst
● Receive all responses in one burst
$redis = new PredisClient();
$pipeline = $redis->pipeline(); // no network I/O
$pipeline->get(“user:$id:name”); // no network I/O
$pipeline->get(“user:$id:email”); // no network I/O
$pipeline->incr(“user:$id:logins”);// no network I/O
$result = $pipeline->execute(); // sends GET/GET/INCR, recvs name, email, login
Single round-trip to the server but operations are not atomic
Transactions
● MULTI command opens transaction
● Send one or more commands
● EXEC closes transaction & receives all results
● Operations execute atomically
$redis = new PredisClient();
$transaction = $redis->transaction(); // sends MULTI
$transaction->get(“user:$id:name”); // sends GET, recvs QUEUED
$transaction->get(“user:$id:email”); // sends GET, recvs QUEUED
$transaction->incr(“user:$id:logins”);// sends INCR, recvs QUEUED
$result = $transaction->execute(); // sends EXEC, recvs name, email, login (post-INCR)
Each operation is a separate round-trip to the server, including the MULTI and EXEC
Atomic pipelines
● Schedule several commands on the client side
● All commands are “wrapped” in a MULTI/EXEC
● Send all commands in one burst, receive responses on one burst
● Operations execute atomically
$redis = new PredisClient();
$atomic = $redis->pipeline([‘atomic’ => true]);
$atomic->get(“user:$id:name”); // no network I/O
$atomic->get(“user:$id:email”); // no network I/O
$atomic->incr(“user:$id:logins”);// no network I/O
$result = $atomic->execute(); // sends MULTI/GET/GET/INCR/EXEC, recvs name, email, login
Atomic pipelines generally are more efficient than raw transactions
Warning:
Ugly code ahead.
Worse:
It’s written in PHP.
In the name of minimizing round-trips
/**
* A do-everything function so opening a user session is a single
* round-trip to the Redis server.
*/
function open_user_session($redis, $userid, $emoji_id, $notifications) {
$pipe = $redis->pipeline();
$pipe->get(“user:$userid:name”);
$pipe->get(“user:$userid:member_of”);
$pipe->hmget(“emoji:$emoji_id”, “tag”, “name”, “image”);
$today = date(“Y-m-d”);
$pipe->incr(“logins:$today”);
$pipe->set(“session:$userid”, time(), “EX”, 600, “NX”);
$pipe->sadd(“members:logged_in”, $userid);
$results = $pipe->execute();
Do-everything functions break encapsulation
● Details of data layout in Redis is exposed
● Changing data structures means changing lots of code—
the “ripple effect”
● Encourages code duplication—tempted to Ctrl+C / Ctrl+V
● Difficult to refactor
● Difficult to maintain
Passing pipeline object to other functions has fundamental problem:
How does the scheduling code receive the results of its read operation(s)?
Transforming & normalizing results
/**
* Do-everything function continued.
*
* In Predis (and other clients) transaction and pipeline
* results are returned in a numeric-indexed array.
*/
function open_user_session($redis, $id, $emoji_id, $notifications) {
// … pipeline is executed as in previous slide …
$user = new User($results[0]);
$user->setMembershipObject(Membership::fromString($results[1]));
$emoji = new Emoji($results[2][1], $results[2][0]);
$emoji->setImage(base64_decode($results[2][2]));
$user->setEmoji($emoji);
StatsD::gauge(‘login_count’, (int) $results[3]);
if ($results[4] != null) $notifications->sessionExtended($id);
if ($results[5] > 0) Syslog::notice(“$id already logged in”);
return $user;
}
Commands are detached from result processing
● Results array is ordered in command-order
● Adding a new command changes index of all results which follow
● Difficult to associate commands with their results
● $results[3][0] is not friendly
● Redis data types don’t necessarily correspond to language data types
● string(“0”) is not FALSE, NULL, nil, undefined, or even an integer in all languages
Even if the code is all contained in a single function,
it’s difficult to match the Redis command with its result(s)
The full function
function open_user_session($redis, $id, $emoji_id, $notifications) {
$pipe = $redis->pipeline();
$pipe->get(“user:$id:name”);
$pipe->get(“user:$id:member_of”);
$pipe->hmget(“emoji:$emoji_id”, “tag”, “name”, “image”);
$today = date(“Y-m-d”);
$pipe->incr(“logins:$today”);
$pipe->set(“session:$id”, “EX”, 600, “NX”);
$pipe->sadd(“members:logged_in”, $id);
$results = $pipe->execute();
$user = new User($results[0]);
$user->setMembershipObject(Membership::fromString($results[1]));
$emoji = new Emoji($results[2][1], $results[2][0]);
$emoji->setImage(base64_decode($results[2][2]));
$user->setEmoji($emoji);
StatsD::gauge(‘login_count’, (int) $results[3]);
if ($results[4] != null) $notifications->sessionExtended($id);
if ($results[5] > 0) Syslog::notice(“$id already logged in”);
return $user;
}
In a clean world, the
do-everything function would be
broken up into functions, each
bite-sized Redis operation(s).
The hard reality:
Production-scale requirements
often require packing
operations in pipelines.
The hard reality:
Production-scale requirements
often create balls of
code mud.
Promises & futures
with Redis
Promises & futures
First developed in the 1970s
“Rediscovered” in the 2000s for Web
Sometimes called “deferred programming”
The Big Concept:
Bind a costly scheduled operation
with its resulting value(s) upon completion
Promises & futures
Here’s how I’m using these terms:
A Promise object schedules the operation.
The Promise returns a placeholder object for each operation.
The object “receives” the result when the operation completes.
That object is a Future.
Promises & futures with Redis
Going back to a key concept:
Redis pipelines and transactions “schedule” work to be performed later.
$pipeline = $redis->pipeline(); // no network I/O
$pipeline->get(“user:$id:name”); // no network I/O
$pipeline->get(“user:$id:email”); // no network I/O
$pipeline->incr(“user:$id:logins”);// no network I/O
$result = $pipeline->execute(); // sends GET/GET/INCR, recvs name, email, login
This matches perfectly with the promises/futures approach
Promises & futures with Redis
Your Redis client might already have support!
A little searching turned up libraries for NodeJS & Scala
I’m sure there’s more—this is not an exotic concept.
Deferred:
Promises & futures for PHP/Predis
Deferred: Promises & futures for PHP/Predis
Programming with Deferred almost looks like coding with Predis:
$redis = new PredisClient();
$promises = new DeferredPromisesPipeline($redis);
$get_name = $promises->get(“user:$id:name”); // returns DeferredFuture
$hgetall_emoji = $promises->hgetall(“emoji:$emoji_id”); // returns DeferredFuture
$promises->execute(); // network I/O happens here
$name = $get_name->value(); // string
$emoji = $hgetall_emoji->value(); // HGETALL array
Scheduling commands with Deferred
Redis commands return placeholder Future objects:
$get_name = $promises->get(“user:$id:name”); // DeferredFuture
$hgetall_emoji = $promises->hgetall(“emoji:$emoji_id”); // DeferredFuture
Futures hold no value until the Promises object is executed.
In promises/futures parlance, the Futures are unfulfilled.
Fulfilling operations with Deferred
Executing a Promises object fulfills the Future objects:
$promises->execute(); // network I/O happens here (“fulfilled”)
$name = $get_name->value(); // string
$emoji = $hgetall_emoji->value(); // HGETALL array
Once fulfilled, the resulting value may be retrieved with the
value() method.
Transforming results
Often we want to normalize or deserialize Redis results. Futures allows for
transformations:
// DeferredFuture
$username = $promises->get(“user:$id:name”);
// reverse the user’s name upon fulfillment
$username->transform(“strrev”); // strrev() is a PHP function
// network I/O -- strrev() is executed here
$promises->execute();
// user’s name backwards
echo $username->value();
Transformations: A more interesting example
Use transformations to fetch objects instead of arrays of strings:
// $emoji is the DeferredFuture
$emoji = $promises->hmget(“emoji:$id”, “name”, “tag”, “image”);
// $hmget is an array of values
$emoji->transform(function ($hmget) {
$e = new Emoji($hmget[0], $hmget[1]);
$e->load_image(base64_decode($hmget[2]));
return $e; // returns an initialized Emoji object
});
$promises->execute(); // network I/O -- transformation happens here
return $emoji->value(); // returns the initialized Emoji object
Stacking transformations
Multiple transformations may be registered. They are processed in order:
function emoji_image_binary($promises, $id) {
$image_future = $promises->hget(“emoji:$id”, “image”);
$image_future->transform(function ($hget) {
return base64_decode($hget); // this transformation is first
});
return $image_future;
}
$image_md5_future = emoji_image_binary($promises, ‘happy-face’);
$image_md5_future->transform(function ($bin) {
return md5sum($bin); // this transformation is second
});
Make HMGET look like HGETALL
In Predis, HGETALL returns a keyed array (or a map):
$redis->hgetall(“profile:jim”) // [ “name” => “Jim”, “emoji” => “:elephant:” ]
while HMGET returns an indexed array:
$redis->hmget(“profile:jim”, “name”, “emoji”) // [ “Jim”, “:elephant:” ]
If you have a function which uses HMGET in one code path and HGETALL in
another, transformations can smooth out the difference.
Make HMGET look like HGETALL
function getProfile($promises, $username, array $fields = null) {
if (!$fields) {
$future = $promises->hgetall(“profile:$username”);
} else {
$future = $promises->hmget(“profile:$username”, $fields);
$future->transform(function ($hmget) use ($fields) {
return array_combine($fields, $hmget);
});
}
return $future;
}
Binding
Binding allows for transferring the final result to a PHP variable:
$username = null;
$future = $promises->get(“user:$id:name”);
$future->bind($username);
// more conveniently (identical to prior 2 lines)
$promises->get(“user:$id:name”)->bind($username);
$promises->execute(); // $username is now set to a string
return $username;
Transformations + binding
$profile = null;
// get raw user profile data with HGETALL
$future = $promises->hgetall(“user:$id:profile”);
$future->transform(function ($hgetall) {
// initialize UserProfile with HGETALL results
return new UserProfile($hgetall[“name”], $hgetall[“location”], $hgetall[“email”]);
});
// bind UserProfile object to $profile variable
$future->bind($profile);
// fulfill
$promises->execute();
Transformations are always done first, then binding
Reducing
Multiple Futures may be reduced to a single Future:
$registered = $promises->sismember(“users:registered”, $userid);
$validated = $promises->sismember(“users:validated”, $userid);
$confirmed = $promises->sismember(“users:confirmed”, $userid);
// reduce all three SISMEMBERs to a single Future
$is_ready = $promises->reduce($registered, $validated, $confirmed); // returns a DeferredFuture
$is_ready->transform(function (array $results) {
return $results[0] && $results[1] && $results[2];
});
$promises->execute();
return $is_ready->value(); // returns boolean
Putting it all together
The full function
function open_user_session($redis, $id, $emoji_id, $notifications) {
$pipe = $redis->pipeline();
$pipe->get(“user:$id:name”);
$pipe->get(“user:$id:member_of”);
$pipe->hmget(“emoji:$emoji_id”, “tag”, “name”, “image”);
$today = date(“Y-m-d”);
$pipe->incr(“logins:$today”);
$pipe->set(“session:$id”, “EX”, 600, “NX”);
$pipe->sadd(“members:logged_in”, $id);
$results = $pipe->execute();
$user = new User($results[0]);
$user->set_membership_object(Membership::from_string($results[1]));
$emoji = new Emoji($results[2][1], $results[2][0]);
$emoji->set_image(base64_decode($results[2][2]));
$user->set_emoji($emoji);
StatsD::gauge(‘login_count’, (int) $results[3]);
if ($results[4] != null) $notifications->session_extended($id);
if ($results[5] > 0) Syslog::notice(“$id already logged in”);
return $user;
}
class User
// Returns DeferredFuture for User instance
static function getFuture($promises, $id)
{
$name = $promises->get(“user:$id:name”)
$member_of = $promises->get(“user:$id:member_of”);
$user_future = $promises->reduce($name, $member_of)->transform($results) {
$user = new User($results[0]);
$user->set_membership_object(Membership::from_string($results[1]);
return $user;
});
return $user_future;
}
class Emoji
// Returns DeferredFuture for Emoji instance
static function getFuture($promises, $emoji_id)
{
$emoji_future = $promises->hmget(“emoji:$emoji_id”,
“name”, “tag”, “image”);
$emoji_future->transform(function ($hmget) {
$emoji = new Emoji($hmget[0], $hmget[1]);
$emoji->set_image(base64_decode($hmget[2]);
return $emoji;
});
return $emoji_future;
}
class Session
// Starts the session on the Redis cache and notifies if extended
function startSession($promises, $userid, $notifications)
{
$set_future = $promises->set(“session:$userid”, “EX”, 600, “NX”);
$set_future->onFulfilled(function ($set) use ($userid, $notifications) {
if ($set !== null)
$notifications->notify_session_extended($userid);
});
return $set_future;
}
The full function (revised)
function open_user_session($redis, $userid, $emoji_id, $notifications) {
$promises = new DeferredPromisesPipeline($redis);
$user = null;
User::getFuture($promises, $userid)->bind($user);
Emoji::getFuture($promises, $emoji_id)->onFulfilled(function ($emoji) use (&$user) {
$user->set_emoji($emoji);
});
Session::create()->startSession($promises, $userid, $notifications);
LoginTracker::increment($promises);
Members::setLoggedIn($promises, $userid);
$promises->execute();
return $user;
“Show me the code.”
https://github.com/internetarchive/deferred
Questions?
Thank You

More Related Content

What's hot

RedisConf18 - Serving Automated Home Valuation with Redis & Kafka
RedisConf18 - Serving Automated Home Valuation with Redis & KafkaRedisConf18 - Serving Automated Home Valuation with Redis & Kafka
RedisConf18 - Serving Automated Home Valuation with Redis & KafkaRedis Labs
 
RedisConf18 - Redis as a time-series DB
RedisConf18 - Redis as a time-series DBRedisConf18 - Redis as a time-series DB
RedisConf18 - Redis as a time-series DBRedis Labs
 
RedisConf18 - Ultra Scaling with Redis Enterprise
RedisConf18 - Ultra Scaling with Redis EnterpriseRedisConf18 - Ultra Scaling with Redis Enterprise
RedisConf18 - Ultra Scaling with Redis EnterpriseRedis Labs
 
High-Volume Data Collection and Real Time Analytics Using Redis
High-Volume Data Collection and Real Time Analytics Using RedisHigh-Volume Data Collection and Real Time Analytics Using Redis
High-Volume Data Collection and Real Time Analytics Using Rediscacois
 
RedisConf18 - Remote Monitoring & Controlling Scienific Instruments
RedisConf18 - Remote Monitoring & Controlling Scienific InstrumentsRedisConf18 - Remote Monitoring & Controlling Scienific Instruments
RedisConf18 - Remote Monitoring & Controlling Scienific InstrumentsRedis Labs
 
iland Internet Solutions: Leveraging Cassandra for real-time multi-datacenter...
iland Internet Solutions: Leveraging Cassandra for real-time multi-datacenter...iland Internet Solutions: Leveraging Cassandra for real-time multi-datacenter...
iland Internet Solutions: Leveraging Cassandra for real-time multi-datacenter...DataStax Academy
 
RedisConf18 - Redis Enterprise on Cloud Native Platforms
RedisConf18 - Redis Enterprise on Cloud  Native  Platforms RedisConf18 - Redis Enterprise on Cloud  Native  Platforms
RedisConf18 - Redis Enterprise on Cloud Native Platforms Redis Labs
 
RedisConf17 - Operationalizing Redis at Scale
RedisConf17 - Operationalizing Redis at ScaleRedisConf17 - Operationalizing Redis at Scale
RedisConf17 - Operationalizing Redis at ScaleRedis Labs
 
RedisConf18 - Implementing a New Data Structure for Redis
RedisConf18 - Implementing a New Data Structure for Redis  RedisConf18 - Implementing a New Data Structure for Redis
RedisConf18 - Implementing a New Data Structure for Redis Redis Labs
 
Redis Day TLV 2018 - 10 Reasons why Redis should be your Primary Database
Redis Day TLV 2018 - 10 Reasons why Redis should be your Primary DatabaseRedis Day TLV 2018 - 10 Reasons why Redis should be your Primary Database
Redis Day TLV 2018 - 10 Reasons why Redis should be your Primary DatabaseRedis Labs
 
PlayStation and Searchable Cassandra Without Solr (Dustin Pham & Alexander Fi...
PlayStation and Searchable Cassandra Without Solr (Dustin Pham & Alexander Fi...PlayStation and Searchable Cassandra Without Solr (Dustin Pham & Alexander Fi...
PlayStation and Searchable Cassandra Without Solr (Dustin Pham & Alexander Fi...DataStax
 
Message Queuing on a Large Scale: IMVUs stateful real-time message queue for ...
Message Queuing on a Large Scale: IMVUs stateful real-time message queue for ...Message Queuing on a Large Scale: IMVUs stateful real-time message queue for ...
Message Queuing on a Large Scale: IMVUs stateful real-time message queue for ...Jon Watte
 
HadoopCon- Trend Micro SPN Hadoop Overview
HadoopCon- Trend Micro SPN Hadoop OverviewHadoopCon- Trend Micro SPN Hadoop Overview
HadoopCon- Trend Micro SPN Hadoop OverviewYafang Chang
 
Managing 50K+ Redis Databases Over 4 Public Clouds ... with a Tiny Devops Team
Managing 50K+ Redis Databases Over 4 Public Clouds ... with a Tiny Devops TeamManaging 50K+ Redis Databases Over 4 Public Clouds ... with a Tiny Devops Team
Managing 50K+ Redis Databases Over 4 Public Clouds ... with a Tiny Devops TeamRedis Labs
 
Webinar: Diagnosing Apache Cassandra Problems in Production
Webinar: Diagnosing Apache Cassandra Problems in ProductionWebinar: Diagnosing Apache Cassandra Problems in Production
Webinar: Diagnosing Apache Cassandra Problems in ProductionDataStax Academy
 
RedisConf17 - Lyft - Geospatial at Scale - Daniel Hochman
RedisConf17 - Lyft - Geospatial at Scale - Daniel HochmanRedisConf17 - Lyft - Geospatial at Scale - Daniel Hochman
RedisConf17 - Lyft - Geospatial at Scale - Daniel HochmanRedis Labs
 
Troubleshooting Cassandra (J.B. Langston, DataStax) | C* Summit 2016
Troubleshooting Cassandra (J.B. Langston, DataStax) | C* Summit 2016Troubleshooting Cassandra (J.B. Langston, DataStax) | C* Summit 2016
Troubleshooting Cassandra (J.B. Langston, DataStax) | C* Summit 2016DataStax
 
RedisConf17 - Redis in High Traffic Adtech Stack
RedisConf17 - Redis in High Traffic Adtech StackRedisConf17 - Redis in High Traffic Adtech Stack
RedisConf17 - Redis in High Traffic Adtech StackRedis Labs
 
What's new with enterprise Redis - Leena Joshi, Redis Labs
What's new with enterprise Redis - Leena Joshi, Redis LabsWhat's new with enterprise Redis - Leena Joshi, Redis Labs
What's new with enterprise Redis - Leena Joshi, Redis LabsRedis Labs
 

What's hot (20)

RedisConf18 - Serving Automated Home Valuation with Redis & Kafka
RedisConf18 - Serving Automated Home Valuation with Redis & KafkaRedisConf18 - Serving Automated Home Valuation with Redis & Kafka
RedisConf18 - Serving Automated Home Valuation with Redis & Kafka
 
RedisConf18 - Redis as a time-series DB
RedisConf18 - Redis as a time-series DBRedisConf18 - Redis as a time-series DB
RedisConf18 - Redis as a time-series DB
 
RedisConf18 - Ultra Scaling with Redis Enterprise
RedisConf18 - Ultra Scaling with Redis EnterpriseRedisConf18 - Ultra Scaling with Redis Enterprise
RedisConf18 - Ultra Scaling with Redis Enterprise
 
High-Volume Data Collection and Real Time Analytics Using Redis
High-Volume Data Collection and Real Time Analytics Using RedisHigh-Volume Data Collection and Real Time Analytics Using Redis
High-Volume Data Collection and Real Time Analytics Using Redis
 
RedisConf18 - Remote Monitoring & Controlling Scienific Instruments
RedisConf18 - Remote Monitoring & Controlling Scienific InstrumentsRedisConf18 - Remote Monitoring & Controlling Scienific Instruments
RedisConf18 - Remote Monitoring & Controlling Scienific Instruments
 
HDFS Selective Wire Encryption
HDFS Selective Wire EncryptionHDFS Selective Wire Encryption
HDFS Selective Wire Encryption
 
iland Internet Solutions: Leveraging Cassandra for real-time multi-datacenter...
iland Internet Solutions: Leveraging Cassandra for real-time multi-datacenter...iland Internet Solutions: Leveraging Cassandra for real-time multi-datacenter...
iland Internet Solutions: Leveraging Cassandra for real-time multi-datacenter...
 
RedisConf18 - Redis Enterprise on Cloud Native Platforms
RedisConf18 - Redis Enterprise on Cloud  Native  Platforms RedisConf18 - Redis Enterprise on Cloud  Native  Platforms
RedisConf18 - Redis Enterprise on Cloud Native Platforms
 
RedisConf17 - Operationalizing Redis at Scale
RedisConf17 - Operationalizing Redis at ScaleRedisConf17 - Operationalizing Redis at Scale
RedisConf17 - Operationalizing Redis at Scale
 
RedisConf18 - Implementing a New Data Structure for Redis
RedisConf18 - Implementing a New Data Structure for Redis  RedisConf18 - Implementing a New Data Structure for Redis
RedisConf18 - Implementing a New Data Structure for Redis
 
Redis Day TLV 2018 - 10 Reasons why Redis should be your Primary Database
Redis Day TLV 2018 - 10 Reasons why Redis should be your Primary DatabaseRedis Day TLV 2018 - 10 Reasons why Redis should be your Primary Database
Redis Day TLV 2018 - 10 Reasons why Redis should be your Primary Database
 
PlayStation and Searchable Cassandra Without Solr (Dustin Pham & Alexander Fi...
PlayStation and Searchable Cassandra Without Solr (Dustin Pham & Alexander Fi...PlayStation and Searchable Cassandra Without Solr (Dustin Pham & Alexander Fi...
PlayStation and Searchable Cassandra Without Solr (Dustin Pham & Alexander Fi...
 
Message Queuing on a Large Scale: IMVUs stateful real-time message queue for ...
Message Queuing on a Large Scale: IMVUs stateful real-time message queue for ...Message Queuing on a Large Scale: IMVUs stateful real-time message queue for ...
Message Queuing on a Large Scale: IMVUs stateful real-time message queue for ...
 
HadoopCon- Trend Micro SPN Hadoop Overview
HadoopCon- Trend Micro SPN Hadoop OverviewHadoopCon- Trend Micro SPN Hadoop Overview
HadoopCon- Trend Micro SPN Hadoop Overview
 
Managing 50K+ Redis Databases Over 4 Public Clouds ... with a Tiny Devops Team
Managing 50K+ Redis Databases Over 4 Public Clouds ... with a Tiny Devops TeamManaging 50K+ Redis Databases Over 4 Public Clouds ... with a Tiny Devops Team
Managing 50K+ Redis Databases Over 4 Public Clouds ... with a Tiny Devops Team
 
Webinar: Diagnosing Apache Cassandra Problems in Production
Webinar: Diagnosing Apache Cassandra Problems in ProductionWebinar: Diagnosing Apache Cassandra Problems in Production
Webinar: Diagnosing Apache Cassandra Problems in Production
 
RedisConf17 - Lyft - Geospatial at Scale - Daniel Hochman
RedisConf17 - Lyft - Geospatial at Scale - Daniel HochmanRedisConf17 - Lyft - Geospatial at Scale - Daniel Hochman
RedisConf17 - Lyft - Geospatial at Scale - Daniel Hochman
 
Troubleshooting Cassandra (J.B. Langston, DataStax) | C* Summit 2016
Troubleshooting Cassandra (J.B. Langston, DataStax) | C* Summit 2016Troubleshooting Cassandra (J.B. Langston, DataStax) | C* Summit 2016
Troubleshooting Cassandra (J.B. Langston, DataStax) | C* Summit 2016
 
RedisConf17 - Redis in High Traffic Adtech Stack
RedisConf17 - Redis in High Traffic Adtech StackRedisConf17 - Redis in High Traffic Adtech Stack
RedisConf17 - Redis in High Traffic Adtech Stack
 
What's new with enterprise Redis - Leena Joshi, Redis Labs
What's new with enterprise Redis - Leena Joshi, Redis LabsWhat's new with enterprise Redis - Leena Joshi, Redis Labs
What's new with enterprise Redis - Leena Joshi, Redis Labs
 

Similar to RedisConf18 - Writing modular & encapsulated Redis code

Perl Tools for Productivity
Perl Tools for ProductivityPerl Tools for Productivity
Perl Tools for ProductivityTudor Constantin
 
Metarhia: Node.js Macht Frei
Metarhia: Node.js Macht FreiMetarhia: Node.js Macht Frei
Metarhia: Node.js Macht FreiTimur Shemsedinov
 
Learned lessons in a real world project by Luis Rovirosa at PHPMad
Learned lessons in a real world project by Luis Rovirosa at PHPMadLearned lessons in a real world project by Luis Rovirosa at PHPMad
Learned lessons in a real world project by Luis Rovirosa at PHPMadCodium
 
Tech Talk: DevOps at LeanIX @ Startup Camp Berlin
Tech Talk: DevOps at LeanIX @ Startup Camp BerlinTech Talk: DevOps at LeanIX @ Startup Camp Berlin
Tech Talk: DevOps at LeanIX @ Startup Camp BerlinLeanIX GmbH
 
Expanding your impact with programmability in the data center
Expanding your impact with programmability in the data centerExpanding your impact with programmability in the data center
Expanding your impact with programmability in the data centerCisco Canada
 
Php on the Web and Desktop
Php on the Web and DesktopPhp on the Web and Desktop
Php on the Web and DesktopElizabeth Smith
 
SQL in the Hybrid World
SQL in the Hybrid WorldSQL in the Hybrid World
SQL in the Hybrid WorldTanel Poder
 
Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!mold
 
DCEU 18: App-in-a-Box with Docker Application Packages
DCEU 18: App-in-a-Box with Docker Application PackagesDCEU 18: App-in-a-Box with Docker Application Packages
DCEU 18: App-in-a-Box with Docker Application PackagesDocker, Inc.
 
Introduction to interactive data visualisation using R Shiny
Introduction to interactive data visualisation using R ShinyIntroduction to interactive data visualisation using R Shiny
Introduction to interactive data visualisation using R Shinyanamarisaguedes
 
Aad Versteden | State-of-the-art web applications fuelled by Linked Data awar...
Aad Versteden | State-of-the-art web applications fuelled by Linked Data awar...Aad Versteden | State-of-the-art web applications fuelled by Linked Data awar...
Aad Versteden | State-of-the-art web applications fuelled by Linked Data awar...semanticsconference
 
Codebits 2012 - Fast relational web site construction.
Codebits 2012 - Fast relational web site construction.Codebits 2012 - Fast relational web site construction.
Codebits 2012 - Fast relational web site construction.Nelson Gomes
 
Day in a life of a node.js developer
Day in a life of a node.js developerDay in a life of a node.js developer
Day in a life of a node.js developerEdureka!
 
Day In A Life Of A Node.js Developer
Day In A Life Of A Node.js DeveloperDay In A Life Of A Node.js Developer
Day In A Life Of A Node.js DeveloperEdureka!
 
Nagios Conference 2012 - Eric Loyd - Nagios Implementation Case Eastman Kodak...
Nagios Conference 2012 - Eric Loyd - Nagios Implementation Case Eastman Kodak...Nagios Conference 2012 - Eric Loyd - Nagios Implementation Case Eastman Kodak...
Nagios Conference 2012 - Eric Loyd - Nagios Implementation Case Eastman Kodak...Nagios
 

Similar to RedisConf18 - Writing modular & encapsulated Redis code (20)

Docker tlv
Docker tlvDocker tlv
Docker tlv
 
Perl Tools for Productivity
Perl Tools for ProductivityPerl Tools for Productivity
Perl Tools for Productivity
 
Metarhia: Node.js Macht Frei
Metarhia: Node.js Macht FreiMetarhia: Node.js Macht Frei
Metarhia: Node.js Macht Frei
 
Node azure
Node azureNode azure
Node azure
 
Learned lessons in a real world project by Luis Rovirosa at PHPMad
Learned lessons in a real world project by Luis Rovirosa at PHPMadLearned lessons in a real world project by Luis Rovirosa at PHPMad
Learned lessons in a real world project by Luis Rovirosa at PHPMad
 
Tech Talk: DevOps at LeanIX @ Startup Camp Berlin
Tech Talk: DevOps at LeanIX @ Startup Camp BerlinTech Talk: DevOps at LeanIX @ Startup Camp Berlin
Tech Talk: DevOps at LeanIX @ Startup Camp Berlin
 
Redis
RedisRedis
Redis
 
Expanding your impact with programmability in the data center
Expanding your impact with programmability in the data centerExpanding your impact with programmability in the data center
Expanding your impact with programmability in the data center
 
Php on the Web and Desktop
Php on the Web and DesktopPhp on the Web and Desktop
Php on the Web and Desktop
 
SQL in the Hybrid World
SQL in the Hybrid WorldSQL in the Hybrid World
SQL in the Hybrid World
 
Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!Catalyst - refactor large apps with it and have fun!
Catalyst - refactor large apps with it and have fun!
 
Unit 02: Web Technologies (2/2)
Unit 02: Web Technologies (2/2)Unit 02: Web Technologies (2/2)
Unit 02: Web Technologies (2/2)
 
DCEU 18: App-in-a-Box with Docker Application Packages
DCEU 18: App-in-a-Box with Docker Application PackagesDCEU 18: App-in-a-Box with Docker Application Packages
DCEU 18: App-in-a-Box with Docker Application Packages
 
Introduction to interactive data visualisation using R Shiny
Introduction to interactive data visualisation using R ShinyIntroduction to interactive data visualisation using R Shiny
Introduction to interactive data visualisation using R Shiny
 
Aad Versteden | State-of-the-art web applications fuelled by Linked Data awar...
Aad Versteden | State-of-the-art web applications fuelled by Linked Data awar...Aad Versteden | State-of-the-art web applications fuelled by Linked Data awar...
Aad Versteden | State-of-the-art web applications fuelled by Linked Data awar...
 
Software Engineering
Software EngineeringSoftware Engineering
Software Engineering
 
Codebits 2012 - Fast relational web site construction.
Codebits 2012 - Fast relational web site construction.Codebits 2012 - Fast relational web site construction.
Codebits 2012 - Fast relational web site construction.
 
Day in a life of a node.js developer
Day in a life of a node.js developerDay in a life of a node.js developer
Day in a life of a node.js developer
 
Day In A Life Of A Node.js Developer
Day In A Life Of A Node.js DeveloperDay In A Life Of A Node.js Developer
Day In A Life Of A Node.js Developer
 
Nagios Conference 2012 - Eric Loyd - Nagios Implementation Case Eastman Kodak...
Nagios Conference 2012 - Eric Loyd - Nagios Implementation Case Eastman Kodak...Nagios Conference 2012 - Eric Loyd - Nagios Implementation Case Eastman Kodak...
Nagios Conference 2012 - Eric Loyd - Nagios Implementation Case Eastman Kodak...
 

More from Redis Labs

Redis Day Bangalore 2020 - Session state caching with redis
Redis Day Bangalore 2020 - Session state caching with redisRedis Day Bangalore 2020 - Session state caching with redis
Redis Day Bangalore 2020 - Session state caching with redisRedis Labs
 
Protecting Your API with Redis by Jane Paek - Redis Day Seattle 2020
Protecting Your API with Redis by Jane Paek - Redis Day Seattle 2020Protecting Your API with Redis by Jane Paek - Redis Day Seattle 2020
Protecting Your API with Redis by Jane Paek - Redis Day Seattle 2020Redis Labs
 
The Happy Marriage of Redis and Protobuf by Scott Haines of Twilio - Redis Da...
The Happy Marriage of Redis and Protobuf by Scott Haines of Twilio - Redis Da...The Happy Marriage of Redis and Protobuf by Scott Haines of Twilio - Redis Da...
The Happy Marriage of Redis and Protobuf by Scott Haines of Twilio - Redis Da...Redis Labs
 
SQL, Redis and Kubernetes by Paul Stanton of Windocks - Redis Day Seattle 2020
SQL, Redis and Kubernetes by Paul Stanton of Windocks - Redis Day Seattle 2020SQL, Redis and Kubernetes by Paul Stanton of Windocks - Redis Day Seattle 2020
SQL, Redis and Kubernetes by Paul Stanton of Windocks - Redis Day Seattle 2020Redis Labs
 
Rust and Redis - Solving Problems for Kubernetes by Ravi Jagannathan of VMwar...
Rust and Redis - Solving Problems for Kubernetes by Ravi Jagannathan of VMwar...Rust and Redis - Solving Problems for Kubernetes by Ravi Jagannathan of VMwar...
Rust and Redis - Solving Problems for Kubernetes by Ravi Jagannathan of VMwar...Redis Labs
 
Redis for Data Science and Engineering by Dmitry Polyakovsky of Oracle
Redis for Data Science and Engineering by Dmitry Polyakovsky of OracleRedis for Data Science and Engineering by Dmitry Polyakovsky of Oracle
Redis for Data Science and Engineering by Dmitry Polyakovsky of OracleRedis Labs
 
Practical Use Cases for ACLs in Redis 6 by Jamie Scott - Redis Day Seattle 2020
Practical Use Cases for ACLs in Redis 6 by Jamie Scott - Redis Day Seattle 2020Practical Use Cases for ACLs in Redis 6 by Jamie Scott - Redis Day Seattle 2020
Practical Use Cases for ACLs in Redis 6 by Jamie Scott - Redis Day Seattle 2020Redis Labs
 
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020Redis Labs
 
Leveraging Redis for System Monitoring by Adam McCormick of SBG - Redis Day S...
Leveraging Redis for System Monitoring by Adam McCormick of SBG - Redis Day S...Leveraging Redis for System Monitoring by Adam McCormick of SBG - Redis Day S...
Leveraging Redis for System Monitoring by Adam McCormick of SBG - Redis Day S...Redis Labs
 
JSON in Redis - When to use RedisJSON by Jay Won of Coupang - Redis Day Seatt...
JSON in Redis - When to use RedisJSON by Jay Won of Coupang - Redis Day Seatt...JSON in Redis - When to use RedisJSON by Jay Won of Coupang - Redis Day Seatt...
JSON in Redis - When to use RedisJSON by Jay Won of Coupang - Redis Day Seatt...Redis Labs
 
Highly Available Persistent Session Management Service by Mohamed Elmergawi o...
Highly Available Persistent Session Management Service by Mohamed Elmergawi o...Highly Available Persistent Session Management Service by Mohamed Elmergawi o...
Highly Available Persistent Session Management Service by Mohamed Elmergawi o...Redis Labs
 
Anatomy of a Redis Command by Madelyn Olson of Amazon Web Services - Redis Da...
Anatomy of a Redis Command by Madelyn Olson of Amazon Web Services - Redis Da...Anatomy of a Redis Command by Madelyn Olson of Amazon Web Services - Redis Da...
Anatomy of a Redis Command by Madelyn Olson of Amazon Web Services - Redis Da...Redis Labs
 
Building a Multi-dimensional Analytics Engine with RedisGraph by Matthew Goos...
Building a Multi-dimensional Analytics Engine with RedisGraph by Matthew Goos...Building a Multi-dimensional Analytics Engine with RedisGraph by Matthew Goos...
Building a Multi-dimensional Analytics Engine with RedisGraph by Matthew Goos...Redis Labs
 
RediSearch 1.6 by Pieter Cailliau - Redis Day Bangalore 2020
RediSearch 1.6 by Pieter Cailliau - Redis Day Bangalore 2020RediSearch 1.6 by Pieter Cailliau - Redis Day Bangalore 2020
RediSearch 1.6 by Pieter Cailliau - Redis Day Bangalore 2020Redis Labs
 
RedisGraph 2.0 by Pieter Cailliau - Redis Day Bangalore 2020
RedisGraph 2.0 by Pieter Cailliau - Redis Day Bangalore 2020RedisGraph 2.0 by Pieter Cailliau - Redis Day Bangalore 2020
RedisGraph 2.0 by Pieter Cailliau - Redis Day Bangalore 2020Redis Labs
 
RedisTimeSeries 1.2 by Pieter Cailliau - Redis Day Bangalore 2020
RedisTimeSeries 1.2 by Pieter Cailliau - Redis Day Bangalore 2020RedisTimeSeries 1.2 by Pieter Cailliau - Redis Day Bangalore 2020
RedisTimeSeries 1.2 by Pieter Cailliau - Redis Day Bangalore 2020Redis Labs
 
RedisAI 0.9 by Sherin Thomas of Tensorwerk - Redis Day Bangalore 2020
RedisAI 0.9 by Sherin Thomas of Tensorwerk - Redis Day Bangalore 2020RedisAI 0.9 by Sherin Thomas of Tensorwerk - Redis Day Bangalore 2020
RedisAI 0.9 by Sherin Thomas of Tensorwerk - Redis Day Bangalore 2020Redis Labs
 
Rate-Limiting 30 Million requests by Vijay Lakshminarayanan and Girish Koundi...
Rate-Limiting 30 Million requests by Vijay Lakshminarayanan and Girish Koundi...Rate-Limiting 30 Million requests by Vijay Lakshminarayanan and Girish Koundi...
Rate-Limiting 30 Million requests by Vijay Lakshminarayanan and Girish Koundi...Redis Labs
 
Three Pillars of Observability by Rajalakshmi Raji Srinivasan of Site24x7 Zoh...
Three Pillars of Observability by Rajalakshmi Raji Srinivasan of Site24x7 Zoh...Three Pillars of Observability by Rajalakshmi Raji Srinivasan of Site24x7 Zoh...
Three Pillars of Observability by Rajalakshmi Raji Srinivasan of Site24x7 Zoh...Redis Labs
 
Solving Complex Scaling Problems by Prashant Kumar and Abhishek Jain of Myntr...
Solving Complex Scaling Problems by Prashant Kumar and Abhishek Jain of Myntr...Solving Complex Scaling Problems by Prashant Kumar and Abhishek Jain of Myntr...
Solving Complex Scaling Problems by Prashant Kumar and Abhishek Jain of Myntr...Redis Labs
 

More from Redis Labs (20)

Redis Day Bangalore 2020 - Session state caching with redis
Redis Day Bangalore 2020 - Session state caching with redisRedis Day Bangalore 2020 - Session state caching with redis
Redis Day Bangalore 2020 - Session state caching with redis
 
Protecting Your API with Redis by Jane Paek - Redis Day Seattle 2020
Protecting Your API with Redis by Jane Paek - Redis Day Seattle 2020Protecting Your API with Redis by Jane Paek - Redis Day Seattle 2020
Protecting Your API with Redis by Jane Paek - Redis Day Seattle 2020
 
The Happy Marriage of Redis and Protobuf by Scott Haines of Twilio - Redis Da...
The Happy Marriage of Redis and Protobuf by Scott Haines of Twilio - Redis Da...The Happy Marriage of Redis and Protobuf by Scott Haines of Twilio - Redis Da...
The Happy Marriage of Redis and Protobuf by Scott Haines of Twilio - Redis Da...
 
SQL, Redis and Kubernetes by Paul Stanton of Windocks - Redis Day Seattle 2020
SQL, Redis and Kubernetes by Paul Stanton of Windocks - Redis Day Seattle 2020SQL, Redis and Kubernetes by Paul Stanton of Windocks - Redis Day Seattle 2020
SQL, Redis and Kubernetes by Paul Stanton of Windocks - Redis Day Seattle 2020
 
Rust and Redis - Solving Problems for Kubernetes by Ravi Jagannathan of VMwar...
Rust and Redis - Solving Problems for Kubernetes by Ravi Jagannathan of VMwar...Rust and Redis - Solving Problems for Kubernetes by Ravi Jagannathan of VMwar...
Rust and Redis - Solving Problems for Kubernetes by Ravi Jagannathan of VMwar...
 
Redis for Data Science and Engineering by Dmitry Polyakovsky of Oracle
Redis for Data Science and Engineering by Dmitry Polyakovsky of OracleRedis for Data Science and Engineering by Dmitry Polyakovsky of Oracle
Redis for Data Science and Engineering by Dmitry Polyakovsky of Oracle
 
Practical Use Cases for ACLs in Redis 6 by Jamie Scott - Redis Day Seattle 2020
Practical Use Cases for ACLs in Redis 6 by Jamie Scott - Redis Day Seattle 2020Practical Use Cases for ACLs in Redis 6 by Jamie Scott - Redis Day Seattle 2020
Practical Use Cases for ACLs in Redis 6 by Jamie Scott - Redis Day Seattle 2020
 
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020
Moving Beyond Cache by Yiftach Shoolman Redis Labs - Redis Day Seattle 2020
 
Leveraging Redis for System Monitoring by Adam McCormick of SBG - Redis Day S...
Leveraging Redis for System Monitoring by Adam McCormick of SBG - Redis Day S...Leveraging Redis for System Monitoring by Adam McCormick of SBG - Redis Day S...
Leveraging Redis for System Monitoring by Adam McCormick of SBG - Redis Day S...
 
JSON in Redis - When to use RedisJSON by Jay Won of Coupang - Redis Day Seatt...
JSON in Redis - When to use RedisJSON by Jay Won of Coupang - Redis Day Seatt...JSON in Redis - When to use RedisJSON by Jay Won of Coupang - Redis Day Seatt...
JSON in Redis - When to use RedisJSON by Jay Won of Coupang - Redis Day Seatt...
 
Highly Available Persistent Session Management Service by Mohamed Elmergawi o...
Highly Available Persistent Session Management Service by Mohamed Elmergawi o...Highly Available Persistent Session Management Service by Mohamed Elmergawi o...
Highly Available Persistent Session Management Service by Mohamed Elmergawi o...
 
Anatomy of a Redis Command by Madelyn Olson of Amazon Web Services - Redis Da...
Anatomy of a Redis Command by Madelyn Olson of Amazon Web Services - Redis Da...Anatomy of a Redis Command by Madelyn Olson of Amazon Web Services - Redis Da...
Anatomy of a Redis Command by Madelyn Olson of Amazon Web Services - Redis Da...
 
Building a Multi-dimensional Analytics Engine with RedisGraph by Matthew Goos...
Building a Multi-dimensional Analytics Engine with RedisGraph by Matthew Goos...Building a Multi-dimensional Analytics Engine with RedisGraph by Matthew Goos...
Building a Multi-dimensional Analytics Engine with RedisGraph by Matthew Goos...
 
RediSearch 1.6 by Pieter Cailliau - Redis Day Bangalore 2020
RediSearch 1.6 by Pieter Cailliau - Redis Day Bangalore 2020RediSearch 1.6 by Pieter Cailliau - Redis Day Bangalore 2020
RediSearch 1.6 by Pieter Cailliau - Redis Day Bangalore 2020
 
RedisGraph 2.0 by Pieter Cailliau - Redis Day Bangalore 2020
RedisGraph 2.0 by Pieter Cailliau - Redis Day Bangalore 2020RedisGraph 2.0 by Pieter Cailliau - Redis Day Bangalore 2020
RedisGraph 2.0 by Pieter Cailliau - Redis Day Bangalore 2020
 
RedisTimeSeries 1.2 by Pieter Cailliau - Redis Day Bangalore 2020
RedisTimeSeries 1.2 by Pieter Cailliau - Redis Day Bangalore 2020RedisTimeSeries 1.2 by Pieter Cailliau - Redis Day Bangalore 2020
RedisTimeSeries 1.2 by Pieter Cailliau - Redis Day Bangalore 2020
 
RedisAI 0.9 by Sherin Thomas of Tensorwerk - Redis Day Bangalore 2020
RedisAI 0.9 by Sherin Thomas of Tensorwerk - Redis Day Bangalore 2020RedisAI 0.9 by Sherin Thomas of Tensorwerk - Redis Day Bangalore 2020
RedisAI 0.9 by Sherin Thomas of Tensorwerk - Redis Day Bangalore 2020
 
Rate-Limiting 30 Million requests by Vijay Lakshminarayanan and Girish Koundi...
Rate-Limiting 30 Million requests by Vijay Lakshminarayanan and Girish Koundi...Rate-Limiting 30 Million requests by Vijay Lakshminarayanan and Girish Koundi...
Rate-Limiting 30 Million requests by Vijay Lakshminarayanan and Girish Koundi...
 
Three Pillars of Observability by Rajalakshmi Raji Srinivasan of Site24x7 Zoh...
Three Pillars of Observability by Rajalakshmi Raji Srinivasan of Site24x7 Zoh...Three Pillars of Observability by Rajalakshmi Raji Srinivasan of Site24x7 Zoh...
Three Pillars of Observability by Rajalakshmi Raji Srinivasan of Site24x7 Zoh...
 
Solving Complex Scaling Problems by Prashant Kumar and Abhishek Jain of Myntr...
Solving Complex Scaling Problems by Prashant Kumar and Abhishek Jain of Myntr...Solving Complex Scaling Problems by Prashant Kumar and Abhishek Jain of Myntr...
Solving Complex Scaling Problems by Prashant Kumar and Abhishek Jain of Myntr...
 

Recently uploaded

Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 

Recently uploaded (20)

Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 

RedisConf18 - Writing modular & encapsulated Redis code

  • 1. Writing modular & encapsulated Redis code Jim Nelson jnelson@archive.org Internet Archive
  • 2. Internet Archive Universal Access to All Knowledge ● Founded 1996, based in San Francisco ● Archive of digital and physical media ● Includes Web, books, music, film, software & more ● Digital holdings: over 35 petabytes & counting ● Over 1 million users per day ● Key collections & services: ○ Wayback Machine ○ Grateful Dead live concert collection ○ The Emularity: in-browser emulation of 8-bit software, IBM PC, Mac, & now handhelds like Speak-and-Spell
  • 3. Internet Archive ♡ Redis ● Caching & directory lookup backed by 10-node sharded Redis cluster ● Sharding performed client-side via consistent hashing (PHP, Predis) ● Each node supported by two replicated mirrors (fail-over) ● Specialized Redis instances also used throughout IA’s services, including ○ Wayback Machine ○ Search (item metadata and full-text) ○ Administrative & usage tracking ○ …and more
  • 4. Before we get started ● I’m assuming you’ve written Redis client code already ● You don’t need to know the exact details of the Redis protocol… ● …but you need some understanding of how Redis “works” ○ single-threaded ○ different data types (strings, hash, sorted sets, etc.) ○ transactions (MULTI/EXEC) This presentation uses PHP sample code and Predis (a PHP Redis client) but most concepts presented should work in other languages & clients
  • 6. “Baby, where have you been my whole life?” ● Quick, quick, quick ○ Quick to code ○ Quick to debug ○ Quick response times ○ Quick to model data ● Logical, well-defined command structure ● Atomicity ● Flexibility over rigor Learning only a handful of straightforward concepts, I felt I had a solid working understanding of Redis
  • 8. “It’s complicated.” (As in, Facebook-it’s-complicated.) ● Application code mixed with data model code ○ Little-to-no separation between data logic and business logic ● Relational data often sprayed across separate Redis buckets ○ No clean way to normalize or deserialize complex objects if they’re sharded across keys ● Performance considerations trump clean coding practices ○ Modularity ignored in order to minimize round-trips to server
  • 9. The temptation of Redis is that it looks like a collections framework.
  • 10. What’s missing? All the things I know and love about designing clean code. Modularity Encapsulation Readability
  • 11. What is encapsulation? Encapsulation “says that a program should be divided into modules that hide data structures behind an interface of procedure calls. The purpose of this is to allow you to change the underlying data structure without causing a large ripple effect across the system.” –Martin Fowler, martinfowler.com
  • 13. Sending & receiving data Redis (and most Redis clients) offer different modes of operation: ● Immediate mode ● Pipeline mode ● Transaction mode ● Atomic pipeline mode
  • 14. Immediate mode Send one command, receive one response. That’s it. No, really. $redis = new PredisClient(); $name = $redis->get(“user:$id:name”); // sends GET, recvs name $email = $redis->get(“user:$id:email”); // sends GET, recvs email $login_count = $redis->incr(“user:$id:logins”) // sends INCR, recvs incremented number Simple enough!
  • 15. Pipeline mode ● Collect (or schedule) several commands on the client side ● Send all commands in one burst ● Receive all responses in one burst $redis = new PredisClient(); $pipeline = $redis->pipeline(); // no network I/O $pipeline->get(“user:$id:name”); // no network I/O $pipeline->get(“user:$id:email”); // no network I/O $pipeline->incr(“user:$id:logins”);// no network I/O $result = $pipeline->execute(); // sends GET/GET/INCR, recvs name, email, login Single round-trip to the server but operations are not atomic
  • 16. Transactions ● MULTI command opens transaction ● Send one or more commands ● EXEC closes transaction & receives all results ● Operations execute atomically $redis = new PredisClient(); $transaction = $redis->transaction(); // sends MULTI $transaction->get(“user:$id:name”); // sends GET, recvs QUEUED $transaction->get(“user:$id:email”); // sends GET, recvs QUEUED $transaction->incr(“user:$id:logins”);// sends INCR, recvs QUEUED $result = $transaction->execute(); // sends EXEC, recvs name, email, login (post-INCR) Each operation is a separate round-trip to the server, including the MULTI and EXEC
  • 17. Atomic pipelines ● Schedule several commands on the client side ● All commands are “wrapped” in a MULTI/EXEC ● Send all commands in one burst, receive responses on one burst ● Operations execute atomically $redis = new PredisClient(); $atomic = $redis->pipeline([‘atomic’ => true]); $atomic->get(“user:$id:name”); // no network I/O $atomic->get(“user:$id:email”); // no network I/O $atomic->incr(“user:$id:logins”);// no network I/O $result = $atomic->execute(); // sends MULTI/GET/GET/INCR/EXEC, recvs name, email, login Atomic pipelines generally are more efficient than raw transactions
  • 20. In the name of minimizing round-trips /** * A do-everything function so opening a user session is a single * round-trip to the Redis server. */ function open_user_session($redis, $userid, $emoji_id, $notifications) { $pipe = $redis->pipeline(); $pipe->get(“user:$userid:name”); $pipe->get(“user:$userid:member_of”); $pipe->hmget(“emoji:$emoji_id”, “tag”, “name”, “image”); $today = date(“Y-m-d”); $pipe->incr(“logins:$today”); $pipe->set(“session:$userid”, time(), “EX”, 600, “NX”); $pipe->sadd(“members:logged_in”, $userid); $results = $pipe->execute();
  • 21. Do-everything functions break encapsulation ● Details of data layout in Redis is exposed ● Changing data structures means changing lots of code— the “ripple effect” ● Encourages code duplication—tempted to Ctrl+C / Ctrl+V ● Difficult to refactor ● Difficult to maintain Passing pipeline object to other functions has fundamental problem: How does the scheduling code receive the results of its read operation(s)?
  • 22. Transforming & normalizing results /** * Do-everything function continued. * * In Predis (and other clients) transaction and pipeline * results are returned in a numeric-indexed array. */ function open_user_session($redis, $id, $emoji_id, $notifications) { // … pipeline is executed as in previous slide … $user = new User($results[0]); $user->setMembershipObject(Membership::fromString($results[1])); $emoji = new Emoji($results[2][1], $results[2][0]); $emoji->setImage(base64_decode($results[2][2])); $user->setEmoji($emoji); StatsD::gauge(‘login_count’, (int) $results[3]); if ($results[4] != null) $notifications->sessionExtended($id); if ($results[5] > 0) Syslog::notice(“$id already logged in”); return $user; }
  • 23. Commands are detached from result processing ● Results array is ordered in command-order ● Adding a new command changes index of all results which follow ● Difficult to associate commands with their results ● $results[3][0] is not friendly ● Redis data types don’t necessarily correspond to language data types ● string(“0”) is not FALSE, NULL, nil, undefined, or even an integer in all languages Even if the code is all contained in a single function, it’s difficult to match the Redis command with its result(s)
  • 24. The full function function open_user_session($redis, $id, $emoji_id, $notifications) { $pipe = $redis->pipeline(); $pipe->get(“user:$id:name”); $pipe->get(“user:$id:member_of”); $pipe->hmget(“emoji:$emoji_id”, “tag”, “name”, “image”); $today = date(“Y-m-d”); $pipe->incr(“logins:$today”); $pipe->set(“session:$id”, “EX”, 600, “NX”); $pipe->sadd(“members:logged_in”, $id); $results = $pipe->execute(); $user = new User($results[0]); $user->setMembershipObject(Membership::fromString($results[1])); $emoji = new Emoji($results[2][1], $results[2][0]); $emoji->setImage(base64_decode($results[2][2])); $user->setEmoji($emoji); StatsD::gauge(‘login_count’, (int) $results[3]); if ($results[4] != null) $notifications->sessionExtended($id); if ($results[5] > 0) Syslog::notice(“$id already logged in”); return $user; }
  • 25. In a clean world, the do-everything function would be broken up into functions, each bite-sized Redis operation(s).
  • 26. The hard reality: Production-scale requirements often require packing operations in pipelines.
  • 27. The hard reality: Production-scale requirements often create balls of code mud.
  • 29. Promises & futures First developed in the 1970s “Rediscovered” in the 2000s for Web Sometimes called “deferred programming” The Big Concept: Bind a costly scheduled operation with its resulting value(s) upon completion
  • 30. Promises & futures Here’s how I’m using these terms: A Promise object schedules the operation. The Promise returns a placeholder object for each operation. The object “receives” the result when the operation completes. That object is a Future.
  • 31. Promises & futures with Redis Going back to a key concept: Redis pipelines and transactions “schedule” work to be performed later. $pipeline = $redis->pipeline(); // no network I/O $pipeline->get(“user:$id:name”); // no network I/O $pipeline->get(“user:$id:email”); // no network I/O $pipeline->incr(“user:$id:logins”);// no network I/O $result = $pipeline->execute(); // sends GET/GET/INCR, recvs name, email, login This matches perfectly with the promises/futures approach
  • 32. Promises & futures with Redis Your Redis client might already have support! A little searching turned up libraries for NodeJS & Scala I’m sure there’s more—this is not an exotic concept.
  • 34. Deferred: Promises & futures for PHP/Predis Programming with Deferred almost looks like coding with Predis: $redis = new PredisClient(); $promises = new DeferredPromisesPipeline($redis); $get_name = $promises->get(“user:$id:name”); // returns DeferredFuture $hgetall_emoji = $promises->hgetall(“emoji:$emoji_id”); // returns DeferredFuture $promises->execute(); // network I/O happens here $name = $get_name->value(); // string $emoji = $hgetall_emoji->value(); // HGETALL array
  • 35. Scheduling commands with Deferred Redis commands return placeholder Future objects: $get_name = $promises->get(“user:$id:name”); // DeferredFuture $hgetall_emoji = $promises->hgetall(“emoji:$emoji_id”); // DeferredFuture Futures hold no value until the Promises object is executed. In promises/futures parlance, the Futures are unfulfilled.
  • 36. Fulfilling operations with Deferred Executing a Promises object fulfills the Future objects: $promises->execute(); // network I/O happens here (“fulfilled”) $name = $get_name->value(); // string $emoji = $hgetall_emoji->value(); // HGETALL array Once fulfilled, the resulting value may be retrieved with the value() method.
  • 37. Transforming results Often we want to normalize or deserialize Redis results. Futures allows for transformations: // DeferredFuture $username = $promises->get(“user:$id:name”); // reverse the user’s name upon fulfillment $username->transform(“strrev”); // strrev() is a PHP function // network I/O -- strrev() is executed here $promises->execute(); // user’s name backwards echo $username->value();
  • 38. Transformations: A more interesting example Use transformations to fetch objects instead of arrays of strings: // $emoji is the DeferredFuture $emoji = $promises->hmget(“emoji:$id”, “name”, “tag”, “image”); // $hmget is an array of values $emoji->transform(function ($hmget) { $e = new Emoji($hmget[0], $hmget[1]); $e->load_image(base64_decode($hmget[2])); return $e; // returns an initialized Emoji object }); $promises->execute(); // network I/O -- transformation happens here return $emoji->value(); // returns the initialized Emoji object
  • 39. Stacking transformations Multiple transformations may be registered. They are processed in order: function emoji_image_binary($promises, $id) { $image_future = $promises->hget(“emoji:$id”, “image”); $image_future->transform(function ($hget) { return base64_decode($hget); // this transformation is first }); return $image_future; } $image_md5_future = emoji_image_binary($promises, ‘happy-face’); $image_md5_future->transform(function ($bin) { return md5sum($bin); // this transformation is second });
  • 40. Make HMGET look like HGETALL In Predis, HGETALL returns a keyed array (or a map): $redis->hgetall(“profile:jim”) // [ “name” => “Jim”, “emoji” => “:elephant:” ] while HMGET returns an indexed array: $redis->hmget(“profile:jim”, “name”, “emoji”) // [ “Jim”, “:elephant:” ] If you have a function which uses HMGET in one code path and HGETALL in another, transformations can smooth out the difference.
  • 41. Make HMGET look like HGETALL function getProfile($promises, $username, array $fields = null) { if (!$fields) { $future = $promises->hgetall(“profile:$username”); } else { $future = $promises->hmget(“profile:$username”, $fields); $future->transform(function ($hmget) use ($fields) { return array_combine($fields, $hmget); }); } return $future; }
  • 42. Binding Binding allows for transferring the final result to a PHP variable: $username = null; $future = $promises->get(“user:$id:name”); $future->bind($username); // more conveniently (identical to prior 2 lines) $promises->get(“user:$id:name”)->bind($username); $promises->execute(); // $username is now set to a string return $username;
  • 43. Transformations + binding $profile = null; // get raw user profile data with HGETALL $future = $promises->hgetall(“user:$id:profile”); $future->transform(function ($hgetall) { // initialize UserProfile with HGETALL results return new UserProfile($hgetall[“name”], $hgetall[“location”], $hgetall[“email”]); }); // bind UserProfile object to $profile variable $future->bind($profile); // fulfill $promises->execute(); Transformations are always done first, then binding
  • 44. Reducing Multiple Futures may be reduced to a single Future: $registered = $promises->sismember(“users:registered”, $userid); $validated = $promises->sismember(“users:validated”, $userid); $confirmed = $promises->sismember(“users:confirmed”, $userid); // reduce all three SISMEMBERs to a single Future $is_ready = $promises->reduce($registered, $validated, $confirmed); // returns a DeferredFuture $is_ready->transform(function (array $results) { return $results[0] && $results[1] && $results[2]; }); $promises->execute(); return $is_ready->value(); // returns boolean
  • 45. Putting it all together
  • 46. The full function function open_user_session($redis, $id, $emoji_id, $notifications) { $pipe = $redis->pipeline(); $pipe->get(“user:$id:name”); $pipe->get(“user:$id:member_of”); $pipe->hmget(“emoji:$emoji_id”, “tag”, “name”, “image”); $today = date(“Y-m-d”); $pipe->incr(“logins:$today”); $pipe->set(“session:$id”, “EX”, 600, “NX”); $pipe->sadd(“members:logged_in”, $id); $results = $pipe->execute(); $user = new User($results[0]); $user->set_membership_object(Membership::from_string($results[1])); $emoji = new Emoji($results[2][1], $results[2][0]); $emoji->set_image(base64_decode($results[2][2])); $user->set_emoji($emoji); StatsD::gauge(‘login_count’, (int) $results[3]); if ($results[4] != null) $notifications->session_extended($id); if ($results[5] > 0) Syslog::notice(“$id already logged in”); return $user; }
  • 47. class User // Returns DeferredFuture for User instance static function getFuture($promises, $id) { $name = $promises->get(“user:$id:name”) $member_of = $promises->get(“user:$id:member_of”); $user_future = $promises->reduce($name, $member_of)->transform($results) { $user = new User($results[0]); $user->set_membership_object(Membership::from_string($results[1]); return $user; }); return $user_future; }
  • 48. class Emoji // Returns DeferredFuture for Emoji instance static function getFuture($promises, $emoji_id) { $emoji_future = $promises->hmget(“emoji:$emoji_id”, “name”, “tag”, “image”); $emoji_future->transform(function ($hmget) { $emoji = new Emoji($hmget[0], $hmget[1]); $emoji->set_image(base64_decode($hmget[2]); return $emoji; }); return $emoji_future; }
  • 49. class Session // Starts the session on the Redis cache and notifies if extended function startSession($promises, $userid, $notifications) { $set_future = $promises->set(“session:$userid”, “EX”, 600, “NX”); $set_future->onFulfilled(function ($set) use ($userid, $notifications) { if ($set !== null) $notifications->notify_session_extended($userid); }); return $set_future; }
  • 50. The full function (revised) function open_user_session($redis, $userid, $emoji_id, $notifications) { $promises = new DeferredPromisesPipeline($redis); $user = null; User::getFuture($promises, $userid)->bind($user); Emoji::getFuture($promises, $emoji_id)->onFulfilled(function ($emoji) use (&$user) { $user->set_emoji($emoji); }); Session::create()->startSession($promises, $userid, $notifications); LoginTracker::increment($promises); Members::setLoggedIn($promises, $userid); $promises->execute(); return $user;
  • 51. “Show me the code.” https://github.com/internetarchive/deferred