SlideShare ist ein Scribd-Unternehmen logo
1 von 49
Downloaden Sie, um offline zu lesen
Cachopo.
Scalable Stateful
Services
Abel Muiño
Lead Software
Engineer at
@cabifyDev
@amuino
The old world. Stateless services.
📱 databaseservice
📱
📱
📱 databaseservice
📱
📱
📱
📱
📱
📱 databaseservice
📱
📱
📱
📱
📱
service
📱 databaseservice
📱
📱
📱
📱
📱
service
📱📱
📱📱
📱 databaseservice
📱
📱
📱
📱
📱
service
📱📱
📱📱
service
📱 databaseservice
📱
📱
📱
📱
📱
service
📱📱
📱📱
service
📱
📱
📱
📱
📱
📱
📱📱
📱📱
service
service
service
service
2011 2012 2013 2014 2015 2016
Completed Journeys
(Axis has no legend because NDA and stuff)
Data shipping.
📱 databaseservice
📱
📱
📱
📱
📱
service
📱📱
📱📱
service
The new world. Stateful services.
📱 databaseservice
📱
📱
📱
📱
📱
service
📱📱
📱📱
service
More on Stateful Services:
"Building Scalable Stateful Services"
by Caitie McCaffrey on Youtube
Cooking Cachopo
Cachopo. The core ideas:
- move data to where it is used
- protect your database
- operate in memory
Cachopo. Use cases:
- full dataset in memory
- allows full in-memory queries
- core dataset
- hot dataset in memory
- allows only “by id” queries
- authorisations / online users / …
Constraints. Build what we can
during offsite (1 week).
Cachopo. Use cases:
- hot dataset in memory
- allows only “by id” queries
- authorisations / online users / …
- full dataset in memory
- allows full in-memory queries
- core dataset
Essentially we built a read-
through cache. ¯_(ツ)_/¯
Simplest API
{:ok, pid} = Cachopo.start_link(

adapter: MyAdapter,

adapter_config: [foo: “bar"])
{:ok, value} = Cachopo.get(pid, "my_key")
config = [adapter: MyAdapter,
adapter_config: [foo: “bar”]]
children = [
worker(Cachopo, [config, [name: :my_cache]]),
]
opts = [strategy: :one_for_one]
Supervisor.start_link(children, opts)
{:ok, value} = Cachopo.get(:my_cache, "my_key")
Supervision Tree 👍
In process storage. 

Using erlang’s ETS
Erlang’s :ets module
Access to C code to store erlang terms, so there
is minimum overhead (no serialization to/
deserialization from, e.g. JSON)
At the top level, stores tuples. One of the
positions of the tuple is the primary key.
Out of heap
ETS data is stored outside erlang processes, so it
does not impact GC
Key-Value store
Fast access to “rows” by key.
Also allows scans and some matching syntax
not yet used for Cachopo.
No mailbox
ETS is designed for highly concurrent access.
Unlike a process mailbox, there is no serialisation
of the messages.
No network
No rountrips, no errors, no format conversions…
ETS. The S is for Speed.
ETSCache
Adapter
Cachopo
Database
Adapter. You keep using that
word…
defmodule Cachopo.Adapter do
@type id :: Cachopo.Cache.id
@type config :: Spec.config
@type key :: term
@type value :: term
@type on_get :: {:ok, value} | :not_found | {:error, term}
@callback setup(config) :: config
@callback start_link(id, config) :: Supervisor.on_start
@callback get(id, config, key) :: on_get
end
The Adapter
⚠ cache invalidation!
defmodule Cachopo.Adapter do
...
@callback changes(id, config) :: Enumerable.t
end
Return of the Adapter
Push, don't pull. Updates to the
storage are published to the service.
ETSCache
Adapter
Cachopo
Database
Invalidator
Couchdb adapter.
Cabify <3 Couch.
Live changes feed
Clients can receive new versions as they are
written. Globally for a database or filtered.
Cachopo uses this on start.
Replay changes
Clients can “rewind” the feed to a given
change.
Cachopo uses this to recover from
disconnections so that no change is lost.
Couchdb Adapter. Three
implementation highlights.
HTTPoison streaming mode
The changes feed may be infinite, Cachopo
parses it line by line.
Stream API for changes feed
Store changes in the Changes Consumer, read
them using familiar iteration.
Connection behaviour
Simplifies connect/disonnect management,
backoffs on the Changes Consumer. Build on top
of GenServer.
defmodule Cachopo.Adapter.Couchdb.Client do
def follow(%{url: url,
http_client: http_client,
http_client_options: opts},
last_seq  "now",
handler  self()) do
url = changes_url_from(url, last_seq)
opts = opts ++ [stream_to: handler,
recv_timeout: :infinity]
http_client.get(url, [], opts)
end
end
1. HTTPoison streaming mode
def handle_async_message(%HTTPoison.AsyncChunk{chunk: chunk})
when chunk in ["n", ""],
do: :ignore
def handle_async_message(%HTTPoison.AsyncChunk{chunk: chunk}),
do: Parser.change(chunk)
def handle_async_message(%HTTPoison.AsyncStatus{code: 200}),
do: :ignore
def handle_async_message(%HTTPoison.AsyncStatus{} = message),
do: {:error, {:unexpected_status, message}}
def handle_async_message(%HTTPoison.AsyncEnd{}),
do: :closed
def handle_async_message(_anything),
do: :ignore
1. HTTPoison streaming mode
defmodule Cachopo.Adapter.Couchdb.Changes.Consumer do
def handle_info(message, %{client: client} = state) do
case client.handle_async_message(message) do
...
# parses and buffers or delivers changes
...
end
end
end
1. HTTPoison streaming mode
Stream API for changes
feed. Stream.resource/3
Stream.resource(

start_fun,

next_fun, 

after_fun

)
start_fun
Starts a new consumer process that reads &
buffers changes.
next_fun
Retrieves a batch of buffered changes from the
consumer process.

If the buffer is empty, the requester is left waiting
and the next change will be delivered
immediately.
after_fun
No op.
defmodule Cachopo.Adapter.Couchdb.Changes do
defp start_fun(sup_mod, sup, config) do
fn ->
{:ok, pid} = sup_mod.start_changes_consumer(sup, config)
pid
end
end
defp next_changes_fun(consumer_mod) do
fn pid ->
changes = consumer_mod.pop_many(pid)
{changes, pid}
end
end
end
2. Stream API for changes feed
defmodule Cachopo.Adapter.Couchdb.Changes.Consumer do
def handle_call(:pop_many, from, state) do
case State.pop_all_changes(state) do
{:ok, changes, new_state} ->
{:reply, changes, new_state}
:empty ->
{:noreply, State.set_waiting(state, from)}
end
end
end
2. Stream API for changes feed
Keep caller
waiting
Store caller pid for fast
response when data arrives
defmodule Cachopo.Adapter.Couchdb.Changes.Consumer do
defp process(change, seq_num, state) do
state = State.set_seq_num(state, seq_num)
case State.pop_waiting(state) do
{:ok, from, new_state} ->
GenServer.reply(from, [change])
new_state
:empty ->
State.push_change(state, change)
end
end
end
2. Stream API for changes feed
Store sequence
number to allow
recovery
If there was a client
waiting, reply.
Otherwise, just
buffer
defmodule Cachopo.Adapter.Couchdb.Changes.Consumer do
use Connection
def init({config, client}),
do: {:connect, :init, State.new(config, client)}
def connect(_source, %{backoff: backoff} = state) do
case follow(state) do
{:ok, _info} -> {:ok, state}
{:error, _reason} -> {:backoff, backoff, state}
end
end
end
3. Connection behaviour
Benchmarking. 

The unprofessional kind.
Request times. Couchdb in localhost, no load,
small documents.
Couchdb endpoint
[info] GET /couch/test
[info] Sent 200 in 25ms
[info] GET /couch/test
[info] Sent 200 in 1ms
[info] GET /couch/test
[info] Sent 200 in 1ms
[info] GET /couch/test
[info] Sent 200 in 1ms
Cachopo endpoint
[info] GET /document/test
[info] Sent 200 in 11ms
[info] GET /document/test
[info] Sent 200 in 67µs
[info] GET /document/test
[info] Sent 200 in 65µs
[info] GET /document/test
[info] Sent 200 in 66µs
Phoenix
Cachopo
Phoenix
Cachopo
Artillery CouchdbPhoenix
Cachopo
Mean request time (s). Synthetic concurrent served
requests.
0
1500
3000
4500
6000
1000 5000 10000 25000
Cachopo Couch
Questions? Show me the code?
Thanks!
@amuino
@cabifyDev

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

Continuous Testing with Molecule, Ansible, and GitHub Actions
Continuous Testing with Molecule, Ansible, and GitHub ActionsContinuous Testing with Molecule, Ansible, and GitHub Actions
Continuous Testing with Molecule, Ansible, and GitHub Actions
 
Fluentd - road to v1 -
Fluentd - road to v1 -Fluentd - road to v1 -
Fluentd - road to v1 -
 
Communication in Python and the C10k problem
Communication in Python and the C10k problemCommunication in Python and the C10k problem
Communication in Python and the C10k problem
 
Embulk at Treasure Data
Embulk at Treasure DataEmbulk at Treasure Data
Embulk at Treasure Data
 
Gearman and CodeIgniter
Gearman and CodeIgniterGearman and CodeIgniter
Gearman and CodeIgniter
 
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...
 
How Ansible Makes Automation Easy
How Ansible Makes Automation EasyHow Ansible Makes Automation Easy
How Ansible Makes Automation Easy
 
CPAN Dependency Heaven
CPAN Dependency HeavenCPAN Dependency Heaven
CPAN Dependency Heaven
 
Capistrano
CapistranoCapistrano
Capistrano
 
Intro to PSGI and Plack
Intro to PSGI and PlackIntro to PSGI and Plack
Intro to PSGI and Plack
 
Gearman - Job Queue
Gearman - Job QueueGearman - Job Queue
Gearman - Job Queue
 
Deployment with capistrano
Deployment with capistranoDeployment with capistrano
Deployment with capistrano
 
Queue your work
Queue your workQueue your work
Queue your work
 
Deploying Symfony | symfony.cat
Deploying Symfony | symfony.catDeploying Symfony | symfony.cat
Deploying Symfony | symfony.cat
 
Making Symofny shine with Varnish - SymfonyCon Madrid 2014
Making Symofny shine with Varnish - SymfonyCon Madrid 2014Making Symofny shine with Varnish - SymfonyCon Madrid 2014
Making Symofny shine with Varnish - SymfonyCon Madrid 2014
 
Puppet for dummies - ZendCon 2011 Edition
Puppet for dummies - ZendCon 2011 EditionPuppet for dummies - ZendCon 2011 Edition
Puppet for dummies - ZendCon 2011 Edition
 
Getting Started with Capistrano
Getting Started with CapistranoGetting Started with Capistrano
Getting Started with Capistrano
 
Monitor-Driven Development Using Ansible
Monitor-Driven Development Using AnsibleMonitor-Driven Development Using Ansible
Monitor-Driven Development Using Ansible
 
Puppet Development Workflow
Puppet Development WorkflowPuppet Development Workflow
Puppet Development Workflow
 
Chef conf-2014
Chef conf-2014Chef conf-2014
Chef conf-2014
 

Ähnlich wie Cachopo - Scalable Stateful Services - Madrid Elixir Meetup

Optimizing CakePHP 2.x Apps
Optimizing CakePHP 2.x AppsOptimizing CakePHP 2.x Apps
Optimizing CakePHP 2.x Apps
Juan Basso
 

Ähnlich wie Cachopo - Scalable Stateful Services - Madrid Elixir Meetup (20)

Real-World Pulsar Architectural Patterns
Real-World Pulsar Architectural PatternsReal-World Pulsar Architectural Patterns
Real-World Pulsar Architectural Patterns
 
Into The Box 2018 Ortus Keynote
Into The Box 2018 Ortus KeynoteInto The Box 2018 Ortus Keynote
Into The Box 2018 Ortus Keynote
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
Optimizing CakePHP 2.x Apps
Optimizing CakePHP 2.x AppsOptimizing CakePHP 2.x Apps
Optimizing CakePHP 2.x Apps
 
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense SolutionsSpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
SpringOne Tour: Spring Recipes: A Collection of Common-Sense Solutions
 
Fargate 를 이용한 ECS with VPC 1부
Fargate 를 이용한 ECS with VPC 1부Fargate 를 이용한 ECS with VPC 1부
Fargate 를 이용한 ECS with VPC 1부
 
Implementing Comet using PHP
Implementing Comet using PHPImplementing Comet using PHP
Implementing Comet using PHP
 
Improving PHP Application Performance with APC
Improving PHP Application Performance with APCImproving PHP Application Performance with APC
Improving PHP Application Performance with APC
 
Stress Testing at Twitter: a tale of New Year Eves
Stress Testing at Twitter: a tale of New Year EvesStress Testing at Twitter: a tale of New Year Eves
Stress Testing at Twitter: a tale of New Year Eves
 
DevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on KubernetesDevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on Kubernetes
 
Dataflow vs spark streaming
Dataflow vs spark streamingDataflow vs spark streaming
Dataflow vs spark streaming
 
Virtual Bash! A Lunchtime Introduction to Kafka
Virtual Bash! A Lunchtime Introduction to KafkaVirtual Bash! A Lunchtime Introduction to Kafka
Virtual Bash! A Lunchtime Introduction to Kafka
 
Continuous Delivery: The Dirty Details
Continuous Delivery: The Dirty DetailsContinuous Delivery: The Dirty Details
Continuous Delivery: The Dirty Details
 
Apache Traffic Server
Apache Traffic ServerApache Traffic Server
Apache Traffic Server
 
PipelineAI + TensorFlow AI + Spark ML + Kuberenetes + Istio + AWS SageMaker +...
PipelineAI + TensorFlow AI + Spark ML + Kuberenetes + Istio + AWS SageMaker +...PipelineAI + TensorFlow AI + Spark ML + Kuberenetes + Istio + AWS SageMaker +...
PipelineAI + TensorFlow AI + Spark ML + Kuberenetes + Istio + AWS SageMaker +...
 
Scaling drupal with confidence - Tweentribune Casestudy
Scaling drupal with confidence - Tweentribune CasestudyScaling drupal with confidence - Tweentribune Casestudy
Scaling drupal with confidence - Tweentribune Casestudy
 
Low latency in java 8 v5
Low latency in java 8 v5Low latency in java 8 v5
Low latency in java 8 v5
 
101 ways to configure kafka - badly
101 ways to configure kafka - badly101 ways to configure kafka - badly
101 ways to configure kafka - badly
 
Google App Engine for Java v0.0.2
Google App Engine for Java v0.0.2Google App Engine for Java v0.0.2
Google App Engine for Java v0.0.2
 
Xke - Introduction to Apache Camel
Xke - Introduction to Apache CamelXke - Introduction to Apache Camel
Xke - Introduction to Apache Camel
 

Mehr von Abel Muíño (6)

Ahora eres coste de estructura - SCPNA 2023
Ahora eres coste de estructura - SCPNA 2023Ahora eres coste de estructura - SCPNA 2023
Ahora eres coste de estructura - SCPNA 2023
 
Hello elixir (and otp)
Hello elixir (and otp)Hello elixir (and otp)
Hello elixir (and otp)
 
We had no idea what we were doing
We had no idea what we were doingWe had no idea what we were doing
We had no idea what we were doing
 
Diseña una empresa
Diseña una empresaDiseña una empresa
Diseña una empresa
 
Maven 3… so what?
Maven 3… so what?Maven 3… so what?
Maven 3… so what?
 
Iam New And Noteworthy
Iam New And NoteworthyIam New And Noteworthy
Iam New And Noteworthy
 

Kürzlich hochgeladen

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 

Kürzlich hochgeladen (20)

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 

Cachopo - Scalable Stateful Services - Madrid Elixir Meetup