SlideShare a Scribd company logo
1 of 93
Download to read offline
WRITING REDIS IN PYTHON
WITH ASYNCIO
James Saryerwinnie / @jsaryer
GOALS
‣ How to structure a “larger” network server application
‣ Request/Response structure
‣ Publish/Subscribe
‣ Blocking queues
ABOUT ME
‣ AWS CLI
‣ Boto3/botocore/boto
‣ JMESPath
‣ AWS Shell
‣ Chalice
s Really Work (version 1.0) Create your own cartoon at www.projectc
customer
ned it
How the project leader
understood it
How the analyst designed
it
How the programmer
wrote it
How the business
consultant described it
http://www.projectcartoon.com/cartoon/3
How the authors envisioned it
How Projects Really Work (version 1.0)
How the customer
explained it
How the project leader
understood it
How the analyst designed
it
How
version 1.0) Create your own cartoon at www.projectcartoon.com
w the project leader
understood it
How the analyst designed
it
How the programmer
wrote it
How the business
consultant described it
What might happen here
REDIS
‣ Data structure server
‣ Set and get key value pairs
‣ Values can be more than string
RedisClient
GET foo
bar
RedisClient
SET foo bar
OK
RedisClient
LPOP foo
a
RedisClient
RPUSH foo a
RPUSH foo b
RPUSH foo c LRANGE foo 0 2
b, c
REQUEST / RESPONSE
RedisClient
GET foo
bar
What we want
server.py
import asyncio
loop = asyncio.get_event_loop()
coro = loop.create_server(RedisServerProtocol, '127.0.0.1', 6379)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
server.py
import asyncio
loop = asyncio.get_event_loop()
coro = loop.create_server(RedisServerProtocol, '127.0.0.1', 6379)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
server.py
import asyncio
loop = asyncio.get_event_loop()
coro = loop.create_server(RedisServerProtocol, '127.0.0.1', 6379)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
server.py
import asyncio
loop = asyncio.get_event_loop()
coro = loop.create_server(RedisServerProtocol, '127.0.0.1', 6379)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
server.py
import asyncio
loop = asyncio.get_event_loop()
coro = loop.create_server(RedisServerProtocol, '127.0.0.1', 6379)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
protocol.py
class RedisServerProtocol(asyncio.Protocol):
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
pass
How do these work?
Let’s look under the hood
server.py
import asyncio
loop = asyncio.get_event_loop()
coro = loop.create_server(RedisServerProtocol, '127.0.0.1', 6379)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
server.py
import asyncio
loop = asyncio.get_event_loop()
coro = loop.create_server(RedisServerProtocol, '127.0.0.1', 6379)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
asyncio/selector_events.py
def _accept_connection2(
self, protocol_factory, conn, extra, server=None):
protocol = None
transport = None
try:
protocol = protocol_factory() # RedisServerProtocol
waiter = futures.Future(loop=self)
transport = _SelectorSocketTransport(self, sock, protocol,
waiter, extra, server)
# ...
except Exception as exc:
# ...
pass
asyncio/selector_events.py
def _accept_connection2(
self, protocol_factory, conn, extra, server=None):
protocol = None
transport = None
try:
protocol = protocol_factory() # RedisServerProtocol
waiter = futures.Future(loop=self)
transport = _SelectorSocketTransport(self, sock, protocol,
waiter, extra, server)
# ...
except Exception as exc:
# ...
pass
ProtocolTransport
ProtocolTransport
ProtocolTransport
client_connected
client_connected
client_connected
asyncio/selector_events.py
class _SelectorSocketTransport(_SelectorTransport):
def __init__(self, loop, sock, protocol, waiter=None,
extra=None, server=None):
super().__init__(loop, sock, protocol, extra, server)
self._eof = False
self._paused = False
self._loop.call_soon(self._protocol.connection_made, self)
# only start reading when connection_made() has been called
self._loop.call_soon(self._loop.add_reader,
self._sock_fd, self._read_ready)
asyncio/selector_events.py
class _SelectorSocketTransport(_SelectorTransport):
def __init__(self, loop, sock, protocol, waiter=None,
extra=None, server=None):
super().__init__(loop, sock, protocol, extra, server)
self._eof = False
self._paused = False
self._loop.call_soon(self._protocol.connection_made, self)
# only start reading when connection_made() has been called
self._loop.call_soon(self._loop.add_reader,
self._sock_fd, self._read_ready)
asyncio/selector_events.py
class _SelectorSocketTransport(_SelectorTransport):
def __init__(self, loop, sock, protocol, waiter=None,
extra=None, server=None):
super().__init__(loop, sock, protocol, extra, server)
self._eof = False
self._paused = False
self._loop.call_soon(self._protocol.connection_made, self)
# only start reading when connection_made() has been called
self._loop.call_soon(self._loop.add_reader,
self._sock_fd, self._read_ready)
asyncio/selector_events.py
def _read_ready(self):
try:
data = self._sock.recv(self.max_size)
except (BlockingIOError, InterruptedError):
pass
except Exception as exc:
self._fatal_error(exc, 'Fatal read error')
else:
if data:
self._protocol.data_received(data)
else:
pass
asyncio/selector_events.py
def _read_ready(self):
try:
data = self._sock.recv(self.max_size)
except (BlockingIOError, InterruptedError):
pass
except Exception as exc:
self._fatal_error(exc, 'Fatal read error')
else:
if data:
self._protocol.data_received(data)
else:
pass
protocol.py
class RedisServerProtocol(asyncio.Protocol):
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
pass
Callbacks
ProtocolTransport
ProtocolTransport
ProtocolTransport
ProtocolTransport
Event Loop
data_received()
data_received()
data_received()
data_received()
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db):
self._db = db
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
parsed = parser.parse_wire_protocol(data)
# [b"SET", b"foo", b"bar"]
command = parsed[0].lower()
if command == b'get':
response = self._db.get(parsed[1])
elif command == b'set':
response = self._db.set(parsed[1], parsed[2])
wire_response = serializer.serialize_to_wire(response)
self.transport.write(wire_response)
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db):
self._db = db
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
parsed = parser.parse_wire_protocol(data)
# [b"SET", b"foo", b"bar"]
command = parsed[0].lower()
if command == b'get':
response = self._db.get(parsed[1])
elif command == b'set':
response = self._db.set(parsed[1], parsed[2])
wire_response = serializer.serialize_to_wire(response)
self.transport.write(wire_response)
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db):
self._db = db
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
parsed = parser.parse_wire_protocol(data)
# [b"SET", b"foo", b"bar"]
command = parsed[0].lower()
if command == b'get':
response = self._db.get(parsed[1])
elif command == b'set':
response = self._db.set(parsed[1], parsed[2])
wire_response = serializer.serialize_to_wire(response)
self.transport.write(wire_response)
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db):
self._db = db
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
parsed = parser.parse_wire_protocol(data)
# [b"SET", b"foo", b"bar"]
command = parsed[0].lower()
if command == b'get':
response = self._db.get(parsed[1])
elif command == b'set':
response = self._db.set(parsed[1], parsed[2])
wire_response = serializer.serialize_to_wire(response)
self.transport.write(wire_response)
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db):
self._db = db
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
parsed = parser.parse_wire_protocol(data)
# [b"SET", b"foo", b"bar"]
command = parsed[0].lower()
if command == b'get':
response = self._db.get(parsed[1])
elif command == b'set':
response = self._db.set(parsed[1], parsed[2])
wire_response = serializer.serialize_to_wire(response)
self.transport.write(wire_response)
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db):
self._db = db
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
parsed = parser.parse_wire_protocol(data)
# [b"SET", b"foo", b"bar"]
command = parsed[0].lower()
if command == b'get':
response = self._db.get(parsed[1])
elif command == b'set':
response = self._db.set(parsed[1], parsed[2])
wire_response = serializer.serialize_to_wire(response)
self.transport.write(wire_response)
b'*3rn$3rnSETrn$3rnfoorn$3rnbarrn'
b'+OKrn'
rserver/db.py
_DB = {}
class DB:
def __init__(self, db=None):
if db is None:
db = _DB
self._db = db
def get(self, item):
return self._db.get(item)
def set(self, item, value):
self._db[item] = value
return True
‣ DB is in its own separate module
‣ It doesn’t know anything about asyncio
rserver/db.py
class DB:
def rpush(self, item, values):
current_list = self._db.setdefault(item, [])
current_list.extend(values)
return len(current_list)
def lrange(self, key, start, stop):
if stop == -1:
end = None
else:
stop += 1
return self._db.get(key, [])[start:stop]
def lpop(self, key):
value = self._db.get(key, [])
if value:
return value.pop(0)
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def data_received(self, data):
parsed = parser.parse_wire_protocol(data)
# [b"SET", b"foo", b"bar"]
command = parsed[0].lower()
if command == b'get':
response = self._db.get(parsed[1])
elif command == b'set':
response = self._db.set(parsed[1], parsed[2])
elif command == b'rpush':
response = self._db.rpush(parsed[1], parsed[2:])
elif command == b'lrange':
response = self._db.lrange(parsed[1], int(parsed[2]),
int(parsed[3]))
wire_response = serializer.serialize_to_wire(response)
self.transport.write(wire_response)
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def data_received(self, data):
parsed = parser.parse_wire_protocol(data)
# [b"SET", b"foo", b"bar"]
command = parsed[0].lower()
if command == b'get':
response = self._db.get(parsed[1])
elif command == b'set':
response = self._db.set(parsed[1], parsed[2])
elif command == b'rpush':
response = self._db.rpush(parsed[1], parsed[2:])
elif command == b'lrange':
response = self._db.lrange(parsed[1], int(parsed[2]),
int(parsed[3]))
wire_response = serializer.serialize_to_wire(response)
self.transport.write(wire_response)
RedisClient
GET foo
bar
What we have
PUBLISH / SUBSCRIBE
Redis
Client SUBSCRIBE foo
Client SUBSCRIBE foo
Client
PUBLISH foo hello
hello
What we want - PUBLISH/SUBSCRIBE
hello
ProtocolTransport
ProtocolTransport
ProtocolTransport
client_connected
client_connected
client_connected
ProtocolProtocolFactory
Protocol
Protocol
def _accept_connection2(…):
try:
protocol = protocol_factory()
waiter = futures.Future(loop=self)
transport = _SelectorSocketTransport(
self, sock, protocol,
waiter, extra, server)
# ...
except Exception as exc:
# ...
pass
rserver/server.py
class PubSub:
def __init__(self):
self._channels = {}
def subscribe(self, channel, transport):
self._channels.setdefault(channel, []).append(transport)
return ['subscribe', channel, 1]
def publish(self, channel, message):
transports = self._channels.get(channel, [])
message = serializer.serialize_to_wire(
['message', channel, message])
for transport in transports:
transport.write(message)
return len(transports)
rserver/server.py
class PubSub:
def __init__(self):
self._channels = {}
def subscribe(self, channel, transport):
self._channels.setdefault(channel, []).append(transport)
return ['subscribe', channel, 1]
def publish(self, channel, message):
transports = self._channels.get(channel, [])
message = serializer.serialize_to_wire(
['message', channel, message])
for transport in transports:
transport.write(message)
return len(transports)
rserver/server.py
class PubSub:
def __init__(self):
self._channels = {}
def subscribe(self, channel, transport):
self._channels.setdefault(channel, []).append(transport)
return ['subscribe', channel, 1]
def publish(self, channel, message):
transports = self._channels.get(channel, [])
message = serializer.serialize_to_wire(
['message', channel, message])
for transport in transports:
transport.write(message)
return len(transports)
rserver/server.py
class RedisServerProtocol(asyncio.Protocol):
def data_received(self, data):
parsed = parser.parse_wire_protocol(data)
# [COMMAND, arg1, arg2]
command = parsed[0].lower()
if command == b'subscribe':
response = self._pubsub.subscribe(
parsed[1], self.transport)
elif command == b'publish':
response = self._pubsub.publish(parsed[1], parsed[2])
wire_response = serializer.serialize_to_wire(response)
self.transport.write(wire_response)
rserver/server.py
class RedisServerProtocol(asyncio.Protocol):
def data_received(self, data):
parsed = parser.parse_wire_protocol(data)
# [COMMAND, arg1, arg2]
command = parsed[0].lower()
if command == b'subscribe':
response = self._pubsub.subscribe(
parsed[1], self.transport)
elif command == b'publish':
response = self._pubsub.publish(parsed[1], parsed[2])
wire_response = serializer.serialize_to_wire(response)
self.transport.write(wire_response)
server.py
import asyncio
loop = asyncio.get_event_loop()
coro = loop.create_server(RedisServerProtocol, '127.0.0.1', 6379)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
server.py
import asyncio
loop = asyncio.get_event_loop()
factory = ProtocolFactory(
RedisServerProtocol, db.DB(), PubSub(),
)
coro = loop.create_server(factory, '127.0.0.1', 6379)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
rserver/server.py
class ProtocolFactory:
def __init__(self, protocol_cls, *args, **kwargs):
self._protocol_cls = protocol_cls
self._args = args
self._kwargs = kwargs
def __call__(self):
# No arg callable is used to instantiate
# protocols in asyncio.
return self._protocol_cls(*self._args, **self._kwargs)
ProtocolFactory PubSub
ProtocolProtocolProtocol
DB
Transport Transport Transport
BLOCKING LIST POP
Redis
Client BLPOP foo 0
Client BLPOP foo 0
Client
RPUSH foo bar
bar
What we want - BLPOP
How do we do this?
ProtocolFactory KeyBlocker
ProtocolProtocolProtocol
rserver/db.py
from rserver import types
class DB:
def blpop(self, key):
value = self._db.get(key, [])
if value:
element = value.pop(0)
return element
return types.MUST_WAIT
rserver/db.py
from rserver import types
class DB:
def blpop(self, key):
value = self._db.get(key, [])
if value:
element = value.pop(0)
return element
return types.MUST_WAIT
rserver/db.py
from rserver import types
class DB:
def blpop(self, key):
value = self._db.get(key, [])
if value:
element = value.pop(0)
return element
return types.MUST_WAIT
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db, keyblocker, loop):
self._db = db
self._keyblocker = keyblocker
self._loop = loop
def data_received(self, data):
# …
if command == b'blpop':
response = self._db.blpop(
parsed[1], timeout=int(parsed[2]))
if response is types.MUST_WAIT:
q = self._keyblocker.wait_for_key(parsed[1],
self.transport)
self._loop.create_task(q)
return
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db, keyblocker, loop):
self._db = db
self._keyblocker = keyblocker
self._loop = loop
def data_received(self, data):
# …
if command == b'blpop':
response = self._db.blpop(
parsed[1], timeout=int(parsed[2]))
if response is types.MUST_WAIT:
q = self._keyblocker.wait_for_key(parsed[1],
self.transport)
self._loop.create_task(q)
return
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db, keyblocker, loop):
self._db = db
self._keyblocker = keyblocker
self._loop = loop
def data_received(self, data):
# …
if command == b'blpop':
response = self._db.blpop(
parsed[1], timeout=int(parsed[2]))
if response is types.MUST_WAIT:
q = self._keyblocker.wait_for_key(parsed[1],
self.transport)
self._loop.create_task(q)
return
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db, keyblocker, loop):
self._db = db
self._keyblocker = keyblocker
self._loop = loop
def data_received(self, data):
# …
if command == b'blpop':
response = self._db.blpop(
parsed[1], timeout=int(parsed[2]))
if response is types.MUST_WAIT:
q = self._keyblocker.wait_for_key(parsed[1],
self.transport)
self._loop.create_task(q)
return
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def __init__(self, db, keyblocker, loop):
self._db = db
self._keyblocker = keyblocker
self._loop = loop
def data_received(self, data):
# …
if command == b'blpop':
response = self._db.blpop(
parsed[1], timeout=int(parsed[2]))
if response is types.MUST_WAIT:
q = self._keyblocker.wait_for_key(parsed[1],
self.transport)
self._loop.create_task(q)
return
rserver/protocol.py
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def data_received(self, data):
# …
command = parsed[0].lower()
if command == b'rpush':
response = self._db.rpush(parsed[1], parsed[2:])
self._loop.create_task(
self._keyblocker.data_for_key(parsed[1], parsed[2]))
rserver/protocol.py
class RedisServerProtocol(asyncio.Protocol):
def data_received(self, data):
# …
command = parsed[0].lower()
if command == b'rpush':
response = self._db.rpush(parsed[1], parsed[2:])
self._loop.create_task(
self._keyblocker.data_for_key(parsed[1], parsed[2]))
rserver/server.py
class KeyBlocker:
def __init__(self):
self._blocked_keys = {}
async def wait_for_key(self, key, transport):
if key not in self._blocked_keys:
self._blocked_keys[key] = asyncio.Queue()
q = self._blocked_keys[key]
value = await q.get()
transport.write(
serializer.serialize_to_wire(value)
)
async def data_for_key(self, key, value):
_LOG.debug("Running data_for_key: %s, value: %s", key, value)
if key in self._blocked_keys:
q = self._blocked_keys[key]
await q.put(value)
_LOG.debug("item put in q via q.put()")
class KeyBlocker:
def __init__(self):
self._blocked_keys = {}
async def wait_for_key(self, key, transport):
if key not in self._blocked_keys:
self._blocked_keys[key] = asyncio.Queue()
q = self._blocked_keys[key]
value = await q.get()
transport.write(
serializer.serialize_to_wire(value)
)
async def data_for_key(self, key, value):
_LOG.debug("Running data_for_key: %s, value: %s", key, value)
if key in self._blocked_keys:
q = self._blocked_keys[key]
await q.put(value)
_LOG.debug("item put in q via q.put()")
rserver/server.py
class KeyBlocker:
def __init__(self):
self._blocked_keys = {}
async def wait_for_key(self, key, transport):
if key not in self._blocked_keys:
self._blocked_keys[key] = asyncio.Queue()
q = self._blocked_keys[key]
value = await q.get()
transport.write(
serializer.serialize_to_wire(value)
)
async def data_for_key(self, key, value):
_LOG.debug("Running data_for_key: %s, value: %s", key, value)
if key in self._blocked_keys:
q = self._blocked_keys[key]
await q.put(value)
_LOG.debug("item put in q via q.put()")
rserver/server.py
class KeyBlocker:
def __init__(self):
self._blocked_keys = {}
async def wait_for_key(self, key, transport):
if key not in self._blocked_keys:
self._blocked_keys[key] = asyncio.Queue()
q = self._blocked_keys[key]
value = await q.get()
transport.write(
serializer.serialize_to_wire(value)
)
async def data_for_key(self, key, value):
_LOG.debug("Running data_for_key: %s, value: %s", key, value)
if key in self._blocked_keys:
q = self._blocked_keys[key]
await q.put(value)
_LOG.debug("item put in q via q.put()")
rserver/server.py
rserver/server.py
class KeyBlocker:
def __init__(self):
self._blocked_keys = {}
async def wait_for_key(self, key, transport):
if key not in self._blocked_keys:
self._blocked_keys[key] = asyncio.Queue()
q = self._blocked_keys[key]
value = await q.get()
transport.write(
serializer.serialize_to_wire(value)
)
async def data_for_key(self, key, value):
_LOG.debug("Running data_for_key: %s, value: %s", key, value)
if key in self._blocked_keys:
q = self._blocked_keys[key]
await q.put(value)
_LOG.debug("item put in q via q.put()")
Event Loop
wait_for_key
Event Loop
q.get()
wait_for_key
Event Loop
q.get()
wait_for_key
Event Loop
yield
q.get()
wait_for_key
Event Loop
yield
q.get()
wait_for_key
Event Loop
yield
future
q.get()
wait_for_key
Event Loop
yield
future
q.get()
wait_for_key
Event Loop
yield
future
data_for_key
q.get()
wait_for_key
Event Loop
yield
future
q.put()
data_for_key
q.get()
wait_for_key
Event Loop
yield
future
q.put()
data_for_key
value
q.get()
wait_for_key
Event Loop
yield
future
q.put()
data_for_key
value
q.get()
wait_for_key
Event Loop
yield
q.put()
data_for_key
value
q.get()
wait_for_key
Event Loop
yield
q.put()
data_for_key
value
q.get()
wait_for_key
Event Loop
value
rserver/server.py
class KeyBlocker:
def __init__(self):
self._blocked_keys = {}
async def wait_for_key(self, key, transport):
if key not in self._blocked_keys:
self._blocked_keys[key] = asyncio.Queue()
q = self._blocked_keys[key]
value = await q.get()
transport.write(
serializer.serialize_to_wire(value)
)
ADDITIONAL CONSIDERATIONS
‣ “Real” parsing is more complicated
‣ Pub/sub handles clients disconnecting
‣ Pub/sub globs
‣ Blocking queues can wait on multiple keys
PERFORMANCE
‣ redis-benchmark -n 100000 -t set,get -c 50
‣ redis-server: 82563 requests per second (gets/sets)
‣ pyredis-server: 24192 requests per second
‣ pyredis-server (uvloop): 38285 requests per second
WHAT WE LEARNED
‣ Transports and Protocols
‣ Simple request response
‣ Publish / Subscribe
‣ Blocking queue like behavior
THANKS!
‣ For more info: @jsaryer

More Related Content

What's hot

node.js practical guide to serverside javascript
node.js practical guide to serverside javascriptnode.js practical guide to serverside javascript
node.js practical guide to serverside javascriptEldar Djafarov
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 
Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기JeongHun Byeon
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf Conference
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby CoreHiroshi SHIBATA
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your AppLuca Mearelli
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojobpmedley
 
Using ngx_lua in UPYUN
Using ngx_lua in UPYUNUsing ngx_lua in UPYUN
Using ngx_lua in UPYUNCong Zhang
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rackdanwrong
 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...Codemotion
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016Manoj Kumar
 
Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with JasmineLeon van der Grient
 
Docker & CoreOS at Utah Gophers
Docker & CoreOS at Utah GophersDocker & CoreOS at Utah Gophers
Docker & CoreOS at Utah GophersJosh Braegger
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with JasmineTim Tyrrell
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony TechniquesKris Wallsmith
 
What’s new in ECMAScript 6.0
What’s new in ECMAScript 6.0What’s new in ECMAScript 6.0
What’s new in ECMAScript 6.0Eyal Vardi
 
Real time server
Real time serverReal time server
Real time serverthepian
 
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...Ville Mattila
 

What's hot (20)

node.js practical guide to serverside javascript
node.js practical guide to serverside javascriptnode.js practical guide to serverside javascript
node.js practical guide to serverside javascript
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby Core
 
ES6: The Awesome Parts
ES6: The Awesome PartsES6: The Awesome Parts
ES6: The Awesome Parts
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
 
Follow the White Rabbit - Message Queues with PHP
Follow the White Rabbit - Message Queues with PHPFollow the White Rabbit - Message Queues with PHP
Follow the White Rabbit - Message Queues with PHP
 
Using ngx_lua in UPYUN
Using ngx_lua in UPYUNUsing ngx_lua in UPYUN
Using ngx_lua in UPYUN
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rack
 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Testing Backbone applications with Jasmine
Testing Backbone applications with JasmineTesting Backbone applications with Jasmine
Testing Backbone applications with Jasmine
 
Docker & CoreOS at Utah Gophers
Docker & CoreOS at Utah GophersDocker & CoreOS at Utah Gophers
Docker & CoreOS at Utah Gophers
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with Jasmine
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
What’s new in ECMAScript 6.0
What’s new in ECMAScript 6.0What’s new in ECMAScript 6.0
What’s new in ECMAScript 6.0
 
Real time server
Real time serverReal time server
Real time server
 
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
 

Similar to Writing Redis in Python with asyncio

Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)Wesley Beary
 
fog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloudfog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the CloudWesley Beary
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.Mike Brevoort
 
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011Nick Sieger
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkDaniel Spector
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js frameworkBen Lin
 
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011Torquebox OSCON Java 2011
Torquebox OSCON Java 2011tobiascrawley
 
IBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js MicroservicesIBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js MicroservicesChris Bailey
 
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Brian Sam-Bodden
 
JRuby with Java Code in Data Processing World
JRuby with Java Code in Data Processing WorldJRuby with Java Code in Data Processing World
JRuby with Java Code in Data Processing WorldSATOSHI TAGOMORI
 
Node Interactive: Node.js Performance and Highly Scalable Micro-Services
Node Interactive: Node.js Performance and Highly Scalable Micro-ServicesNode Interactive: Node.js Performance and Highly Scalable Micro-Services
Node Interactive: Node.js Performance and Highly Scalable Micro-ServicesChris Bailey
 
CouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 HourCouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 HourPeter Friese
 
Container (Docker) Orchestration Tools
Container (Docker) Orchestration ToolsContainer (Docker) Orchestration Tools
Container (Docker) Orchestration ToolsDhilipsiva DS
 
An intro to Docker, Terraform, and Amazon ECS
An intro to Docker, Terraform, and Amazon ECSAn intro to Docker, Terraform, and Amazon ECS
An intro to Docker, Terraform, and Amazon ECSYevgeniy Brikman
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...bobmcwhirter
 
Step into serverless into the box 2018
Step into serverless into the box 2018Step into serverless into the box 2018
Step into serverless into the box 2018Ortus Solutions, Corp
 

Similar to Writing Redis in Python with asyncio (20)

Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Fabric Python Lib
Fabric Python LibFabric Python Lib
Fabric Python Lib
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
 
fog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloudfog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloud
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
JRuby + Rails = Awesome Java Web Framework at Jfokus 2011
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
 
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
 
IBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js MicroservicesIBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js Microservices
 
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
 
JRuby with Java Code in Data Processing World
JRuby with Java Code in Data Processing WorldJRuby with Java Code in Data Processing World
JRuby with Java Code in Data Processing World
 
Node Interactive: Node.js Performance and Highly Scalable Micro-Services
Node Interactive: Node.js Performance and Highly Scalable Micro-ServicesNode Interactive: Node.js Performance and Highly Scalable Micro-Services
Node Interactive: Node.js Performance and Highly Scalable Micro-Services
 
CouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 HourCouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 Hour
 
Container (Docker) Orchestration Tools
Container (Docker) Orchestration ToolsContainer (Docker) Orchestration Tools
Container (Docker) Orchestration Tools
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
An intro to Docker, Terraform, and Amazon ECS
An intro to Docker, Terraform, and Amazon ECSAn intro to Docker, Terraform, and Amazon ECS
An intro to Docker, Terraform, and Amazon ECS
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
Step into serverless into the box 2018
Step into serverless into the box 2018Step into serverless into the box 2018
Step into serverless into the box 2018
 

Recently uploaded

Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 

Recently uploaded (20)

Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 

Writing Redis in Python with asyncio