Created
October 10, 2019 11:11
-
-
Save bennadel/22001831bc610dc03e0bd1ea7140c5cc to your computer and use it in GitHub Desktop.
Playing With Lists And Blocking Pop Operations In Redis And Lucee 5.2.9.40
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
component | |
output = false | |
hint = "I define the application settings and event handlers." | |
{ | |
// Configure the application runtime. | |
this.name = "RedisListWithJsonExploration"; | |
this.applicationTimeout = createTimeSpan( 0, 1, 0, 0 ); | |
this.sessionManagement = false; | |
// Setup the mappings for our path evaluation. | |
this.webrootDir = getDirectoryFromPath( getCurrentTemplatePath() ); | |
this.mappings = { | |
"/": this.webrootDir, | |
"/javaloader": "#this.webrootDir#vendor/JavaLoader/javaloader/", | |
"/JavaLoaderFactory": "#this.webrootDir#vendor/JavaLoaderFactory/", | |
"/jedis": "#this.webrootDir#vendor/jedis-2.9.3/" | |
}; | |
// --- | |
// EVENT METHODS. | |
// --- | |
/** | |
* I get called once when the application is being initialized. | |
*/ | |
public boolean function onApplicationStart() { | |
var javaLoaderFactory = new JavaLoaderFactory.JavaLoaderFactory(); | |
application.javaLoaderForJedis = javaLoaderFactory.getJavaLoader([ | |
expandPath( "/jedis/commons-pool2-2.4.3.jar" ), | |
expandPath( "/jedis/jedis-2.9.3.jar" ), | |
expandPath( "/jedis/slf4j-api-1.7.22.jar" ) | |
]); | |
var jedisConfig = application.javaLoaderForJedis | |
.create( "redis.clients.jedis.JedisPoolConfig" ) | |
.init() | |
; | |
application.jedisPool = application.javaLoaderForJedis | |
.create( "redis.clients.jedis.JedisPool" ) | |
.init( jedisConfig, "127.0.0.1" ) | |
; | |
return( true ); | |
} | |
/** | |
* I get called once at the start of each request. | |
*/ | |
public boolean function onRequestStart() { | |
request.withRedis = this.withRedis; | |
return( true ); | |
} | |
// --- | |
// PUBLIC METHODS. | |
// --- | |
/** | |
* I invoke the given Callback with an instance of a Redis connection from the Jedis | |
* connection pool. The value returned by the Callback is passed-back up to the | |
* calling context. This removes the need to manage the connection in the calling | |
* context. | |
* | |
* @callback I am a Function that is invoked with an instance of a Redis connection. | |
*/ | |
public any function withRedis( required function callback ) { | |
try { | |
var redis = application.jedisPool.getResource(); | |
return( callback( redis ) ); | |
} finally { | |
redis?.close(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfoutput> | |
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
Read a Message | |
</title> | |
</head> | |
<body> | |
<h1> | |
Read a Message | |
</h1> | |
<cfscript> | |
// For the purposes of the demo, we're going to block and listen for about | |
// 30-seconds until the page has to be refreshed (for more messages). | |
startedAt = getTickCount(); | |
cutoffAt = ( startedAt + ( 30 * 1000 ) ); | |
while ( getTickCount() < cutoffAt ) { | |
// Since the BLPOP operation is going to BLOCK the page request, let's | |
// flush data to the Browser incrementally so that we can consume and | |
// display the messages in "realtime" as they are pushed onto the list. | |
cfflush( interval = 1 ); | |
results = request.withRedis( | |
( redis ) => { | |
// NOTE: If the operation doesn't receive any message in 5 | |
// seconds, it will stop blocking and return NULL. | |
return( redis.blpop( 5, [ "list:messages" ] ) ); | |
} | |
); | |
// The result of the BLPOP operation is 2-tuple where the first index is | |
// the name of the key (since we can block on multiple keys at the same | |
// time); and, the second index is the value of the list item. | |
if ( ! isNull( results ) ) { | |
dump( deserializeJson( results[ 2 ] ) ); | |
echo( "<script>scrollTo( 0, 999999 );</script>" ); | |
echo( "<br />" ); | |
} | |
} | |
</cfscript> | |
<a href="#cgi.script_name#">Refresh listener</a> | |
</body> | |
</html> | |
</cfoutput> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfscript> | |
// If the form has been submitted, push a Message onto the List. | |
// -- | |
// NOTE: Each list item is a String that represents a serialized object. | |
if ( form.keyExists( "message" ) && form.message.len() ) { | |
listItem = { | |
"id": createUUID().lcase(), | |
"message": form.message, | |
"createdAt": getTickCount() | |
}; | |
request.withRedis( | |
( redis ) => { | |
redis.rpush( "list:messages", [ serializeJson( listItem ) ] ); | |
} | |
); | |
} | |
</cfscript> | |
<cfoutput> | |
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
Post a Message | |
</title> | |
<link rel="stylesheet" type="text/css" href="./styles.css" /> | |
</head> | |
<body> | |
<h1> | |
Post a Message | |
</h1> | |
<form method="post" action="#cgi.script_name#"> | |
<strong>Message:</strong><br /> | |
<input type="text" name="message" autofocus size="30" /> | |
<button type="submit"> | |
Post | |
</button> | |
</form> | |
</body> | |
</html> | |
</cfoutput> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment