Tame Cloud Complex with F# powered DSLs

Yan Cui
Yan CuiSpeaker at Self
@theburningmonk
tame
|> (cloud <| complexity)
|> with
|> (fsharp >> powered >> DSLs)
Tame Cloud Complex with F# powered DSLs
Tame Cloud Complex with F# powered DSLs
Tame Cloud Complex with F# powered DSLs
Tame Cloud Complex with F# powered DSLs
image by nerovivo license : https://creativecommons.org/licenses/by-sa/2.0/
@theburningmonk
Under-Abstraction
@theburningmonk
Oversimplification
@theburningmonk
Impedance Mismatch
@theburningmonk
Amazon
DynamoDB
Amazon
SimpleWorkflow
Amazon
CloudWatch
CASE STUDY
@theburningmonk
F# DSLs. Awesome!
@theburningmonk
Amazon
DynamoDB
Amazon
SimpleWorkflow
Amazon
CloudWatch
CASE STUDY
@theburningmonk
@theburningmonk
managed
key-value store
@theburningmonk
redundancy
9-9s guarantee
@theburningmonk
great performance
@theburningmonk
name your
throughput
@theburningmonk
@theburningmonk
can be changed on-the-fly
@theburningmonk
@theburningmonk
infinitely scalable
(but you still have to pay for it)
@theburningmonk
Hash Key
Range Key
@theburningmonk
Query:
given a hash key
filter on
range key, or
local secondary index
@theburningmonk
Hash Key Range Key
Local Secondary Index
Global Secondary Index
@theburningmonk
Scan:
FULL TABLE search
(performance + cost concern)
@theburningmonk
Hash Key Range Key
Local Secondary Index
Global Secondary Index
Hash Key Range Key
Local Secondary Index
Who are the TOP 3 players in “Starship
X” with a score of at least 1000?
Global Secondary Index
@theburningmonk
@theburningmonk
select GameTitle, UserId, TopScore
from GameScores
where GameTitle = “Starship X”
and TopScore >= 1000
order desc
limit 3
with (NoConsistentRead, Index(GameTitleIndex, true))
DynamoDB.SQL
github.com/fsprojects/DynamoDb.SQL
@theburningmonk
GOAL
Disguise
complexity
@theburningmonk
GOAL
SELECT UserId, TopScore
FROM GameScore
WHERE GameTitle CONTAINS “Zelda”
ORDER DESC
LIMIT 3
WITH (NoConsistentRead)
@theburningmonk
Query
AST
Execution
F# & FParsec*
*www.quanttec.com/fparsec
External DSL
via
@theburningmonk
@theburningmonk
SELECT * FROM GameScore
Abstract Syntax Tree (AST)
FParsec
@theburningmonk
SELECT * FROM GameScore
keyword keyword
* | attribute, attribute, …
table name
@theburningmonk
SELECT * FROM GameScore
type Attributes =
| Asterisk
| Attributes of string[]
@theburningmonk
SELECT * FROM GameScore
type Query =
{
Attributes : Attributes
Table : string
}
@theburningmonk
SELECT * FROM GameScore
Parser for “SELECT” keyword
pSelect
@theburningmonk
SELECT * FROM GameScore
pSelect
let pSelect = skipStringCI "select"
@theburningmonk
SELECT * FROM GameScore
pSelect
let pSelect = skipStringCI "select"
matches the string “select” (Case
Insensitive) and ignores it
@theburningmonk
SELECT * FROM GameScore
pFrom
let pFrom = skipStringCI "from"
@theburningmonk
SELECT * FROM GameScore
Parser for a string that
represents the table name
pTableName
@theburningmonk
SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
@theburningmonk
SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
@theburningmonk
SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
@theburningmonk
SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
@theburningmonk
SELECT * FROM GameScore
pTableName
let isTableName = isLetter <||> isDigit
let pTableName =
many1Satisfy isTableName
parses a sequence of one or
more chars that satisfies the
predicate function
@theburningmonk
SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
@theburningmonk
SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
let pAsterisk = stringCIReturn "*" Asterisk
@theburningmonk
SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
let pAsterisk = stringCIReturn "*" Asterisk
matches the specified string
and return the given value
@theburningmonk
SELECT * FROM GameScore
pAsterisk
*
pAttributeName
UserId, GameTitle, TopScore, …
let isAttributeName = isLetter <||> isDigit
let pAttributeName =
many1Satisfy isAttributeName
@theburningmonk
SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pCommapAsterisk
*
let pComma = skipStringCI ","
@theburningmonk
SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pCommapAsterisk
*
let pAttributeNames =
sepBy1 pAttributeName pComma
@theburningmonk
SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pCommapAsterisk
*
let pAttributeNames =
sepBy1 pAttributeName pComma
parses one or more occurrences of
pAttributeName separated by pComma
@theburningmonk
SELECT * FROM GameScore
UserId, GameTitle, TopScore, …
pAttributeName pComma
sepBy1
pAttributeNames
pAsterisk
*
@theburningmonk
SELECT * FROM GameScore
pAsterisk
*
pAttributeNames
UserId, GameTitle, TopScore, …
@theburningmonk
SELECT * FROM GameScore
pAsterisk
*
pAttributeNames
UserId, GameTitle, TopScore, …
let pAttribute =
pAsterisk <|> pAttributeNames
@theburningmonk
SELECT * FROM GameScore
pAsterisk
*
pAttributeNames
UserId, GameTitle, TopScore, …
let pAttribute =
pAsterisk <|> pAttributeNames
@theburningmonk
SELECT * FROM GameScore
pAsterisk
*
pAttributeNames
UserId, GameTitle, TopScore, …
choice
pAttribute
@theburningmonk
SELECT * FROM GameScore
pAttribute
@theburningmonk
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
@theburningmonk
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
let pQuery =
tuple4 pSelect pAttribute
pFrom pTableName
|>> (fun (_, attributes, _, table) ->
{ Attributes = attributes
Table = table })
@theburningmonk
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
let pQuery =
tuple4 pSelect pAttribute
pFrom pTableName
|>> (fun (_, attributes, _, table) ->
{ Attributes = attributes
Table = table })
@theburningmonk
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
let pQuery =
tuple4 pSelect pAttribute
pFrom pTableName
|>> (fun (_, attributes, _, table) ->
{ Attributes = attributes
Table = table })
@theburningmonk
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
let pQuery =
tuple4 pSelect pAttribute
pFrom pTableName
|>> (fun (_, attributes, _, table) ->
{ Attributes = attributes
Table = table })
Query
@theburningmonk
SELECT * FROM GameScore
pAttribute pTableNamepFrompSelect
tuple4
pQuery
@theburningmonk
@theburningmonk
< 50 lines of code
@theburningmonk
Amazing
F# + FParsec
=
@theburningmonk
Recap
@theburningmonk
@theburningmonk
select GameTitle, UserId, TopScore
from GameScores
where GameTitle = “Starship X”
and TopScore >= 1000
order desc
limit 3
with (NoConsistentRead, Index(GameTitleIndex, true))
@theburningmonk
Amazon
DynamoDB
Amazon
SimpleWorkflow
Amazon
CloudWatch
CASE STUDY
@theburningmonk
@theburningmonk
Decision Worker
@theburningmonk
Decision Worker
Poll
@theburningmonk
Decision Worker
Decision
Task
@theburningmonk
Decision WorkerDecide
@theburningmonk
Activity Worker
Decision Worker
@theburningmonk
Activity Worker
Decision Worker
Poll
@theburningmonk
Activity Worker
Decision Worker
Activity
Task
@theburningmonk
Activity Worker
Decision Worker
Complete
@theburningmonk
Workers can run from
anywhere
@theburningmonk
@theburningmonk
input = “Yan”
result = “Hello Yan!”
Start
Finish
Activity
@theburningmonk
image by Ryan Hageman license : https://creativecommons.org/licenses/by-sa/2.0/
SWF-based Application
API
Heartbeats
Error
Handling
Polling
API
Activity
Worker
Decision
Worker
Heartbeats
Error
Handling
Polling
API
Activity
Worker
Decision
Worker
Heartbeats
Error
Handling
Polling
API
Boilerplate
– Kris Jordan
“Good simplicity is less with
leverage, not less with less.
Good simplicity is complexity
disguised, not complexity denied.”
http://bit.ly/1pOLeKl
Tame Cloud Complex with F# powered DSLs
Start
Finish
Activity
?
@theburningmonk
the workflow is
implied by decision
worker logic…
@theburningmonk
instead..
@theburningmonk
the workflow should
drive decision
worker logic
@theburningmonk
the workflow should
driveautomate
decision worker logic
Amazon
.SimpleWorkflow
.Extensions
github.com/fsprojects/Amazon.SimpleWorkflow.Extensions
@theburningmonk
GOAL
Remove
boilerplates
@theburningmonk
GOAL
Code that matches
the way you think
@theburningmonk
Start
Finish
Activity
Tame Cloud Complex with F# powered DSLs
Tame Cloud Complex with F# powered DSLs
Start
Finish
Activity
Tame Cloud Complex with F# powered DSLs
@theburningmonk
Workflows can be
nested
Tame Cloud Complex with F# powered DSLs
Tame Cloud Complex with F# powered DSLs
input
result
Tame Cloud Complex with F# powered DSLs
@theburningmonk
Recap
Activity
Worker
Decision
Worker
Heartbeats
Error
Handling
Polling
API
Tame Cloud Complex with F# powered DSLs
@theburningmonk
Amazon
DynamoDB
Amazon
SimpleWorkflow
Amazon
CloudWatch
CASE STUDY
@theburningmonk
@theburningmonk
@theburningmonk
@theburningmonk
wanna find
correlations?
@theburningmonk
wanna find
correlations?
you can DIY it!
;-)
@theburningmonk
“what latencies spiked
at the same time as
payment service?”
Amazon
.CloudWatch
.Selector
github.com/fsprojects/Amazon.CloudWatch.Selector
@theburningmonk
Find metrics whose 5
min average exceeded
1 second during last
12 hours
@theburningmonk
cloudWatch.Select(
unitIs “milliseconds” +
average (>) 1000.0
@ last 12 hours
|> intervalOf 5 minutes)
@theburningmonk
cloudWatch.Select(“
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes”)
@theburningmonk
“did any cache
nodes’ CPU spike
yesterday?”
@theburningmonk
cloudWatch.Select(
namespaceLike “elasticache” +
nameLike “cpu” +
max (>) 80.0
@ last 24 hours
|> intervalOf 15 minutes)
@theburningmonk
cloudWatch.Select(
namespaceLike “elasticache” +
nameLike “cpu” +
max (>) 80.0
@ last 24 hours
|> intervalOf 15 minutes)
Regex
@theburningmonk
@theburningmonk
@theburningmonk
@theburningmonk
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
@theburningmonk
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
Filters
@theburningmonk
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
TimeFrame
@theburningmonk
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
Period
@theburningmonk
type Query =
{
Filter : Filter
TimeFrame : TimeFrame
Period : Period option
}
@theburningmonk
Query
Internal
DSL
External
DSL
@theburningmonk
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
@theburningmonk
type MetricTerm = Namespace | Name
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
@theburningmonk
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
@theburningmonk
type MetricTerm = Namespace | Name
type Unit = | Unit
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
| UnitFilter of Unit * (string -> bool)
@theburningmonk
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
@theburningmonk
type MetricTerm = Namespace | Name
type Unit = | Unit
type StatsTerm =
| Average | Min | Max | Sum | SampleCount
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
| UnitFilter of Unit * (string -> bool)
| StatsFilter of StatsTerm * (float -> bool)
@theburningmonk
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
@theburningmonk
type MetricTerm = Namespace | Name
type Unit = | Unit
type StatsTerm =
| Average | Min | Max | Sum | SampleCount
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
| UnitFilter of Unit * (string -> bool)
| StatsFilter of StatsTerm * (float -> bool)
| CompositeFilter of Filter * Filter
@theburningmonk
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
@theburningmonk
type TimeFrame =
| Last of TimeSpan
| Since of DateTime
| Between of DateTime * DateTime
@theburningmonk
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes
@theburningmonk
type Period = | Period of TimeSpan
@theburningmonk
type Query =
{
Filter : Filter
TimeFrame : TimeFrame
Period : Period option
}
@theburningmonk
Active Patterns
a primer on
@theburningmonk
allow patterns to be
abstracted away into
named functions
@theburningmonk
Single-Case Patterns
@theburningmonk
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
| _ ->
failwithf “not a float [%s]” input
@theburningmonk
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
| _ ->
failwithf “not a float [%s]” input
@theburningmonk
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
| _ ->
failwithf “not a float [%s]” input
Float : string -> float
@theburningmonk
match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
@theburningmonk
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
@theburningmonk
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
@theburningmonk
match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
@theburningmonk
match someString with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
let (|Float|) input =
match Double.TryParse input with
| true, n -> n
@theburningmonk
match “42” with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
@theburningmonk
match “boo” with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
Error!!!
@theburningmonk
Partial Patterns
@theburningmonk
let (|Float|_|) input =
match Double.TryParse input with
| true, n -> Some n
| _ -> None
@theburningmonk
let (|Float|_|) input =
match Double.TryParse input with
| true, n -> Some n
| _ -> None
Float : string -> float option
@theburningmonk
match “boo” with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
| _ -> “not a float”
@theburningmonk
match “boo” with
| Float 42.0 -> “ftw”
| Float 11.0 -> “palprime”
| Float x -> sprintf “just %f” x
| _ -> “not a float”
@theburningmonk
Multi-Case Patterns
@theburningmonk
let (|Prime|NotPrime|NaN|) input =
match Double.TryParse input with
| true, n when isPrime n -> Prime n
| true, n -> NotPrime n
| _ -> NaN
@theburningmonk
let (|Prime|NotPrime|NaN|) input =
match Double.TryParse input with
| true, n when isPrime n -> Prime n
| true, n -> NotPrime n
| _ -> NaN
@theburningmonk
let (|Prime|NotPrime|NaN|) input =
match Double.TryParse input with
| true, n when isPrime n -> Prime n
| true, n -> NotPrime n
| _ -> NaN
@theburningmonk
let (|Prime|NotPrime|NaN|) input =
match Double.TryParse input with
| true, n when isPrime n -> Prime n
| true, n -> NotPrime n
| _ -> NaN
@theburningmonk
let (|Prime|NotPrime|NaN|) input =
match Double.TryParse input with
| true, n when isPrime n -> Prime n
| true, n -> NotPrime n
| _ -> NaN
@theburningmonk
match someString with
| Prime n -> …
| NotPrime n -> …
| NaN -> …
@theburningmonk
match someString with
| Prime n & Float 11.0 -> …
| Prime n -> …
| Float 42.0 | Float 8.0 -> …
| NotPrime n -> …
| NaN -> …
@theburningmonk
match someString with
| Prime n & Float 11.0 -> …
| Prime n -> …
| Float 42.0 | Float 8.0 -> …
| NotPrime n -> …
| NaN -> …
@theburningmonk
match someString with
| Prime (IsPalindrome) -> …
| Prime _ -> …
| _ -> …
@theburningmonk
Tokenise
(string -> string list)
@theburningmonk
[
“namespaceIs”; “‘JustEat’”; “and”;
“nameLike”; “‘cpu’”; “and”;
…
]
@theburningmonk
“namespaceIs” “and” …
F# List = LinkedList
“‘JustEat’”
@theburningmonk
“namespaceIs” “and” …
F# List = LinkedList
“namespaceIs” “‘JustEat’” “and”:::: :: tail
cons (::) operator to prepend
“‘JustEat’”
@theburningmonk
“namespaceIs” “and” …
F# List = LinkedList
“namespaceIs” “‘JustEat’” “and”:::: :: tail
match aList with
|
“‘JustEat’”
works as a pattern too!
@theburningmonk
let (|StringCI|_|) (str : string) (input : string) =
if str.ToLower() = input.ToLower()
then Some ()
else None
let (|Float|_|) input =
match System.Double.TryParse input with
| true, n -> Some n
| _ -> None
@theburningmonk
let (|EmptyString|_|) input =
if String.IsNullOrWhiteSpace input
then Some ()
else None
let (|StartsWith|_|) char (input : string) =
if input.[0] = char then Some () else None
let (|EndsWith|_|) char (input : string) =
if input.[input.Length-1] = char
then Some ()
else None
@theburningmonk
let (|QuotedString|_|) (input : string) =
match input with
| EmptyString -> None
| str when str.Length < 2 -> None
| StartsWith ''' & EndsWith ''' ->
Some <| input.Substring(1, input.Length - 2)
| _ -> None
@theburningmonk
let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
@theburningmonk
let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
namespaceIs ‘JustEat’ and
nameLike ‘cpu’ and
…
@theburningmonk
let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
“namespaceIs” “‘JustEat’” :::: …
@theburningmonk
let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
type MetricTerm = Namespace | Name
type Filter =
| MetricFilter of MetricTerm * (string -> bool)
@theburningmonk
let (|NamespaceIs|_|) = function
| StringCI “NamespaceIs" :: QuotedString ns :: tl
-> Some (eqFilter MetricFilter Namespace ns, tl)
| _ -> None
“and” :: “nameLike” :: “‘cpu’” :: “and” :: …
@theburningmonk
let rec loop acc = function
| NamespaceIs (filter, tl)
| NamespaceLike (filter, tl)
| NameIs (filter, tl) | NameLike (filter, tl)
| UnitIs (filter, tl)
| Average (filter, tl) | Sum (filter, tl)
| Min (filter, tl) | Max (filter, tl)
| SampleCount (filter, tl)
-> match tl with
| And tl -> loop (filter::acc) tl
| _ -> flatten (filter::acc), tl
| _ -> failwith “No filters?!?!?”
@theburningmonk
let rec loop acc = function
| NamespaceIs (filter, tl)
| NamespaceLike (filter, tl)
| NameIs (filter, tl) | NameLike (filter, tl)
| UnitIs (filter, tl)
| Average (filter, tl) | Sum (filter, tl)
| Min (filter, tl) | Max (filter, tl)
| SampleCount (filter, tl)
-> match tl with
| And tl -> loop (filter::acc) tl
| _ -> flatten (filter::acc), tl
| _ -> failwith “No filters?!?!?”
@theburningmonk
let rec loop acc = function
| NamespaceIs (filter, tl)
| NamespaceLike (filter, tl)
| NameIs (filter, tl) | NameLike (filter, tl)
| UnitIs (filter, tl)
| Average (filter, tl) | Sum (filter, tl)
| Min (filter, tl) | Max (filter, tl)
| SampleCount (filter, tl)
-> match tl with
| And tl -> loop (filter::acc) tl
| _ -> flatten (filter::acc), tl
| _ -> failwith “No filters?!?!?”
@theburningmonk
let rec loop acc = function
| NamespaceIs (filter, tl)
| NamespaceLike (filter, tl)
| NameIs (filter, tl) | NameLike (filter, tl)
| UnitIs (filter, tl)
| Average (filter, tl) | Sum (filter, tl)
| Min (filter, tl) | Max (filter, tl)
| SampleCount (filter, tl)
-> match tl with
| And tl -> loop (filter::acc) tl
| _ -> flatten (filter::acc), tl
| _ -> failwith “No filters?!?!?”
@theburningmonk
let rec loop acc = function
| NamespaceIs (filter, tl)
| NamespaceLike (filter, tl)
| NameIs (filter, tl) | NameLike (filter, tl)
| UnitIs (filter, tl)
| Average (filter, tl) | Sum (filter, tl)
| Min (filter, tl) | Max (filter, tl)
| SampleCount (filter, tl)
-> match tl with
| And tl -> loop (filter::acc) tl
| _ -> flatten (filter::acc), tl
| _ -> failwith “No filters?!?!?”
@theburningmonk
let parse (input : string) =
input
|> tokenize
|> parseFilter
|> parseTimeFrame
|> parsePeriod
@theburningmonk
Amazing
F#
=
@theburningmonk
usable from anywhere you
can run F# code
e.g. F# REPL, executable, ..
Internal DSL
@theburningmonk
useful for building tools
e.g. CLI, …
External DSL
@theburningmonk
@theburningmonk
@theburningmonk
@theburningmonk
Recap
@theburningmonk
@theburningmonk
@theburningmonk
Amazon
DynamoDB
Amazon
SimpleWorkflow
Amazon
CloudWatch
CASE STUDY
@theburningmonk
theburningmonk.com
github.com/theburningmonk
1 of 215

Recommended

Tame cloud complexity with F#-powered DSLs by
Tame cloud complexity with F#-powered DSLsTame cloud complexity with F#-powered DSLs
Tame cloud complexity with F#-powered DSLsYan Cui
20.8K views204 slides
Python Programming Essentials - M8 - String Methods by
Python Programming Essentials - M8 - String MethodsPython Programming Essentials - M8 - String Methods
Python Programming Essentials - M8 - String MethodsP3 InfoTech Solutions Pvt. Ltd.
1.7K views23 slides
Hidden Gems of Ruby 1.9 by
Hidden Gems of Ruby 1.9Hidden Gems of Ruby 1.9
Hidden Gems of Ruby 1.9Aaron Patterson
2.5K views187 slides
Elixir @ Paris.rb by
Elixir @ Paris.rbElixir @ Paris.rb
Elixir @ Paris.rbGregoire Lejeune
886 views44 slides
using python module: doctest by
using python module: doctestusing python module: doctest
using python module: doctestmitnk
2.2K views20 slides
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09 by
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09Ilya Grigorik
13.2K views46 slides

More Related Content

What's hot

Exploiting Php With Php by
Exploiting Php With PhpExploiting Php With Php
Exploiting Php With PhpJeremy Coates
32.6K views71 slides
Python decorators (中文) by
Python decorators (中文)Python decorators (中文)
Python decorators (中文)Yiwei Chen
1.8K views57 slides
Meck by
MeckMeck
MeckAdam Lindberg
1.2K views39 slides
QConSP 2015 - Dicas de Performance para Aplicações Web by
QConSP 2015 - Dicas de Performance para Aplicações WebQConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações WebFabio Akita
4.1K views164 slides
Argon walkthru 1-26 by
Argon walkthru 1-26Argon walkthru 1-26
Argon walkthru 1-26Nachiketas Ramanujam
422 views29 slides
Functional Pattern Matching on Python by
Functional Pattern Matching on PythonFunctional Pattern Matching on Python
Functional Pattern Matching on PythonDaker Fernandes
5.5K views26 slides

What's hot(10)

Viewers also liked

AWS Lambda from the trenches by
AWS Lambda from the trenchesAWS Lambda from the trenches
AWS Lambda from the trenchesYan Cui
5.3K views200 slides
7 ineffective coding habits many F# programmers don't have by
7 ineffective coding habits many F# programmers don't have7 ineffective coding habits many F# programmers don't have
7 ineffective coding habits many F# programmers don't haveYan Cui
709.5K views207 slides
F# at GameSys by
F# at GameSysF# at GameSys
F# at GameSysYan Cui
5.1K views254 slides
F# in real world (LambdaCon15) by
F# in real world (LambdaCon15)F# in real world (LambdaCon15)
F# in real world (LambdaCon15)Yan Cui
2.9K views184 slides
My adventure with elm (LambdaCon15) by
My adventure with elm (LambdaCon15)My adventure with elm (LambdaCon15)
My adventure with elm (LambdaCon15)Yan Cui
3K views199 slides
How to Make Awesome SlideShares: Tips & Tricks by
How to Make Awesome SlideShares: Tips & TricksHow to Make Awesome SlideShares: Tips & Tricks
How to Make Awesome SlideShares: Tips & TricksSlideShare
3M views17 slides

Viewers also liked(18)

AWS Lambda from the trenches by Yan Cui
AWS Lambda from the trenchesAWS Lambda from the trenches
AWS Lambda from the trenches
Yan Cui5.3K views
7 ineffective coding habits many F# programmers don't have by Yan Cui
7 ineffective coding habits many F# programmers don't have7 ineffective coding habits many F# programmers don't have
7 ineffective coding habits many F# programmers don't have
Yan Cui709.5K views
F# at GameSys by Yan Cui
F# at GameSysF# at GameSys
F# at GameSys
Yan Cui5.1K views
F# in real world (LambdaCon15) by Yan Cui
F# in real world (LambdaCon15)F# in real world (LambdaCon15)
F# in real world (LambdaCon15)
Yan Cui2.9K views
My adventure with elm (LambdaCon15) by Yan Cui
My adventure with elm (LambdaCon15)My adventure with elm (LambdaCon15)
My adventure with elm (LambdaCon15)
Yan Cui3K views
How to Make Awesome SlideShares: Tips & Tricks by SlideShare
How to Make Awesome SlideShares: Tips & TricksHow to Make Awesome SlideShares: Tips & Tricks
How to Make Awesome SlideShares: Tips & Tricks
SlideShare3M views
Moon light garden rockery by Arpit0007
Moon light garden  rockeryMoon light garden  rockery
Moon light garden rockery
Arpit0007427 views
Getting Started With SlideShare by SlideShare
Getting Started With SlideShareGetting Started With SlideShare
Getting Started With SlideShare
SlideShare4M views
AWS Lambda from the Trenches by Yan Cui
AWS Lambda from the TrenchesAWS Lambda from the Trenches
AWS Lambda from the Trenches
Yan Cui5.8K views
Quality, Testing & Agile Methodologies by Johan Hoberg
Quality, Testing & Agile MethodologiesQuality, Testing & Agile Methodologies
Quality, Testing & Agile Methodologies
Johan Hoberg831 views
The Wisdom of David Henke by Josh Clemm
The Wisdom of David HenkeThe Wisdom of David Henke
The Wisdom of David Henke
Josh Clemm20.1K views
General knowledge by nyinyilay
General knowledgeGeneral knowledge
General knowledge
nyinyilay5.1K views
Awarding Behavior & Altering Businesses with WordPress by Brian Richards
Awarding Behavior & Altering Businesses with WordPressAwarding Behavior & Altering Businesses with WordPress
Awarding Behavior & Altering Businesses with WordPress
Brian Richards602 views
Dress Like an Architect, Think Like an Anarchist | Pro-Walk Pro-Bike Pro-Plac... by Andy Boenau
Dress Like an Architect, Think Like an Anarchist | Pro-Walk Pro-Bike Pro-Plac...Dress Like an Architect, Think Like an Anarchist | Pro-Walk Pro-Bike Pro-Plac...
Dress Like an Architect, Think Like an Anarchist | Pro-Walk Pro-Bike Pro-Plac...
Andy Boenau686 views

Similar to Tame Cloud Complex with F# powered DSLs

Tame cloud complexity with F# powered DSLs (build stuff) by
Tame cloud complexity with F# powered DSLs (build stuff)Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)Yan Cui
652 views218 slides
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10 by
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10egpeters
2K views18 slides
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10 by
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10egpeters
534 views18 slides
Cassandra Seattle Tech Startups 3-10-10 by
Cassandra Seattle Tech Startups 3-10-10Cassandra Seattle Tech Startups 3-10-10
Cassandra Seattle Tech Startups 3-10-10egpeters
487 views18 slides
Cassandra Seattle Tech Startups 3-10-10 by
Cassandra Seattle Tech Startups 3-10-10Cassandra Seattle Tech Startups 3-10-10
Cassandra Seattle Tech Startups 3-10-10egpeters
261 views18 slides
Specs Presentation by
Specs PresentationSpecs Presentation
Specs PresentationSynesso
951 views10 slides

Similar to Tame Cloud Complex with F# powered DSLs(20)

Tame cloud complexity with F# powered DSLs (build stuff) by Yan Cui
Tame cloud complexity with F# powered DSLs (build stuff)Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
Yan Cui652 views
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10 by egpeters
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10
egpeters2K views
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10 by egpeters
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10
NoSQL Cassandra Talk for Seattle Tech Startups 3-10-10
egpeters534 views
Cassandra Seattle Tech Startups 3-10-10 by egpeters
Cassandra Seattle Tech Startups 3-10-10Cassandra Seattle Tech Startups 3-10-10
Cassandra Seattle Tech Startups 3-10-10
egpeters487 views
Cassandra Seattle Tech Startups 3-10-10 by egpeters
Cassandra Seattle Tech Startups 3-10-10Cassandra Seattle Tech Startups 3-10-10
Cassandra Seattle Tech Startups 3-10-10
egpeters261 views
Specs Presentation by Synesso
Specs PresentationSpecs Presentation
Specs Presentation
Synesso951 views
SQL and PLSQL features for APEX Developers by Connor McDonald
SQL and PLSQL features for APEX DevelopersSQL and PLSQL features for APEX Developers
SQL and PLSQL features for APEX Developers
Connor McDonald95 views
... now write an interpreter (PHPem 2016) by James Titcumb
... now write an interpreter (PHPem 2016)... now write an interpreter (PHPem 2016)
... now write an interpreter (PHPem 2016)
James Titcumb297 views
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli... by Codemotion
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
Codemotion308 views
Micro-ORM Introduction - Don't overcomplicate by Kiev ALT.NET
Micro-ORM Introduction - Don't overcomplicateMicro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicate
Kiev ALT.NET4.5K views
What you forgot from your Computer Science Degree by Stephen Darlington
What you forgot from your Computer Science DegreeWhat you forgot from your Computer Science Degree
What you forgot from your Computer Science Degree
Stephen Darlington2.5K views
DataMapper by Yehuda Katz
DataMapperDataMapper
DataMapper
Yehuda Katz12.1K views
Falcon初印象 by 勇浩 赖
Falcon初印象Falcon初印象
Falcon初印象
勇浩 赖1K views
Build Lightweight Web Module by Morgan Cheng
Build Lightweight Web ModuleBuild Lightweight Web Module
Build Lightweight Web Module
Morgan Cheng450 views
Perl6 Regexen: Reduce the line noise in your code. by Workhorse Computing
Perl6 Regexen: Reduce the line noise in your code.Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.
Learn Dart And Angular, Get Your Web Development Wings With Kevin Moore by CodeCore
Learn Dart And Angular, Get Your Web Development Wings With Kevin MooreLearn Dart And Angular, Get Your Web Development Wings With Kevin Moore
Learn Dart And Angular, Get Your Web Development Wings With Kevin Moore
CodeCore2.6K views
Itty bittypresentation lrug by Tom Crinson
Itty bittypresentation lrugItty bittypresentation lrug
Itty bittypresentation lrug
Tom Crinson383 views
Itty bittypresentation lrug by Skills Matter
Itty bittypresentation lrugItty bittypresentation lrug
Itty bittypresentation lrug
Skills Matter216 views
SQL Training in Ambala ! Batra Computer Centre by jatin batra
SQL Training in Ambala ! Batra Computer CentreSQL Training in Ambala ! Batra Computer Centre
SQL Training in Ambala ! Batra Computer Centre
jatin batra113 views

More from Yan Cui

How to win the game of trade-offs by
How to win the game of trade-offsHow to win the game of trade-offs
How to win the game of trade-offsYan Cui
21 views84 slides
How to choose the right messaging service by
How to choose the right messaging serviceHow to choose the right messaging service
How to choose the right messaging serviceYan Cui
135 views118 slides
How to choose the right messaging service for your workload by
How to choose the right messaging service for your workloadHow to choose the right messaging service for your workload
How to choose the right messaging service for your workloadYan Cui
65 views113 slides
Patterns and practices for building resilient serverless applications.pdf by
Patterns and practices for building resilient serverless applications.pdfPatterns and practices for building resilient serverless applications.pdf
Patterns and practices for building resilient serverless applications.pdfYan Cui
170 views137 slides
Lambda and DynamoDB best practices by
Lambda and DynamoDB best practicesLambda and DynamoDB best practices
Lambda and DynamoDB best practicesYan Cui
817 views148 slides
Lessons from running AppSync in prod by
Lessons from running AppSync in prodLessons from running AppSync in prod
Lessons from running AppSync in prodYan Cui
1.1K views102 slides

More from Yan Cui(20)

How to win the game of trade-offs by Yan Cui
How to win the game of trade-offsHow to win the game of trade-offs
How to win the game of trade-offs
Yan Cui21 views
How to choose the right messaging service by Yan Cui
How to choose the right messaging serviceHow to choose the right messaging service
How to choose the right messaging service
Yan Cui135 views
How to choose the right messaging service for your workload by Yan Cui
How to choose the right messaging service for your workloadHow to choose the right messaging service for your workload
How to choose the right messaging service for your workload
Yan Cui65 views
Patterns and practices for building resilient serverless applications.pdf by Yan Cui
Patterns and practices for building resilient serverless applications.pdfPatterns and practices for building resilient serverless applications.pdf
Patterns and practices for building resilient serverless applications.pdf
Yan Cui170 views
Lambda and DynamoDB best practices by Yan Cui
Lambda and DynamoDB best practicesLambda and DynamoDB best practices
Lambda and DynamoDB best practices
Yan Cui817 views
Lessons from running AppSync in prod by Yan Cui
Lessons from running AppSync in prodLessons from running AppSync in prod
Lessons from running AppSync in prod
Yan Cui1.1K views
Serverless observability - a hero's perspective by Yan Cui
Serverless observability - a hero's perspectiveServerless observability - a hero's perspective
Serverless observability - a hero's perspective
Yan Cui385 views
How to ship customer value faster with step functions by Yan Cui
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functions
Yan Cui652 views
How serverless changes the cost paradigm by Yan Cui
How serverless changes the cost paradigmHow serverless changes the cost paradigm
How serverless changes the cost paradigm
Yan Cui1.1K views
Why your next serverless project should use AWS AppSync by Yan Cui
Why your next serverless project should use AWS AppSyncWhy your next serverless project should use AWS AppSync
Why your next serverless project should use AWS AppSync
Yan Cui1.3K views
Build social network in 4 weeks by Yan Cui
Build social network in 4 weeksBuild social network in 4 weeks
Build social network in 4 weeks
Yan Cui642 views
Patterns and practices for building resilient serverless applications by Yan Cui
Patterns and practices for building resilient serverless applicationsPatterns and practices for building resilient serverless applications
Patterns and practices for building resilient serverless applications
Yan Cui393 views
How to bring chaos engineering to serverless by Yan Cui
How to bring chaos engineering to serverlessHow to bring chaos engineering to serverless
How to bring chaos engineering to serverless
Yan Cui456 views
Migrating existing monolith to serverless in 8 steps by Yan Cui
Migrating existing monolith to serverless in 8 stepsMigrating existing monolith to serverless in 8 steps
Migrating existing monolith to serverless in 8 steps
Yan Cui402 views
Building a social network in under 4 weeks with Serverless and GraphQL by Yan Cui
Building a social network in under 4 weeks with Serverless and GraphQLBuilding a social network in under 4 weeks with Serverless and GraphQL
Building a social network in under 4 weeks with Serverless and GraphQL
Yan Cui289 views
FinDev as a business advantage in the post covid19 economy by Yan Cui
FinDev as a business advantage in the post covid19 economyFinDev as a business advantage in the post covid19 economy
FinDev as a business advantage in the post covid19 economy
Yan Cui546 views
How to improve lambda cold starts by Yan Cui
How to improve lambda cold startsHow to improve lambda cold starts
How to improve lambda cold starts
Yan Cui867 views
What can you do with lambda in 2020 by Yan Cui
What can you do with lambda in 2020What can you do with lambda in 2020
What can you do with lambda in 2020
Yan Cui1K views
A chaos experiment a day, keeping the outage away by Yan Cui
A chaos experiment a day, keeping the outage awayA chaos experiment a day, keeping the outage away
A chaos experiment a day, keeping the outage away
Yan Cui385 views
How to debug slow lambda response times by Yan Cui
How to debug slow lambda response timesHow to debug slow lambda response times
How to debug slow lambda response times
Yan Cui317 views

Recently uploaded

Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ... by
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...ShapeBlue
114 views12 slides
Igniting Next Level Productivity with AI-Infused Data Integration Workflows by
Igniting Next Level Productivity with AI-Infused Data Integration Workflows Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows Safe Software
373 views86 slides
Ransomware is Knocking your Door_Final.pdf by
Ransomware is Knocking your Door_Final.pdfRansomware is Knocking your Door_Final.pdf
Ransomware is Knocking your Door_Final.pdfSecurity Bootcamp
81 views46 slides
Why and How CloudStack at weSystems - Stephan Bienek - weSystems by
Why and How CloudStack at weSystems - Stephan Bienek - weSystemsWhy and How CloudStack at weSystems - Stephan Bienek - weSystems
Why and How CloudStack at weSystems - Stephan Bienek - weSystemsShapeBlue
172 views13 slides
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ... by
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...ShapeBlue
121 views15 slides
Keynote Talk: Open Source is Not Dead - Charles Schulz - Vates by
Keynote Talk: Open Source is Not Dead - Charles Schulz - VatesKeynote Talk: Open Source is Not Dead - Charles Schulz - Vates
Keynote Talk: Open Source is Not Dead - Charles Schulz - VatesShapeBlue
178 views15 slides

Recently uploaded(20)

Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ... by ShapeBlue
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
ShapeBlue114 views
Igniting Next Level Productivity with AI-Infused Data Integration Workflows by Safe Software
Igniting Next Level Productivity with AI-Infused Data Integration Workflows Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Safe Software373 views
Why and How CloudStack at weSystems - Stephan Bienek - weSystems by ShapeBlue
Why and How CloudStack at weSystems - Stephan Bienek - weSystemsWhy and How CloudStack at weSystems - Stephan Bienek - weSystems
Why and How CloudStack at weSystems - Stephan Bienek - weSystems
ShapeBlue172 views
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ... by ShapeBlue
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
ShapeBlue121 views
Keynote Talk: Open Source is Not Dead - Charles Schulz - Vates by ShapeBlue
Keynote Talk: Open Source is Not Dead - Charles Schulz - VatesKeynote Talk: Open Source is Not Dead - Charles Schulz - Vates
Keynote Talk: Open Source is Not Dead - Charles Schulz - Vates
ShapeBlue178 views
Future of AR - Facebook Presentation by Rob McCarty
Future of AR - Facebook PresentationFuture of AR - Facebook Presentation
Future of AR - Facebook Presentation
Rob McCarty54 views
Digital Personal Data Protection (DPDP) Practical Approach For CISOs by Priyanka Aash
Digital Personal Data Protection (DPDP) Practical Approach For CISOsDigital Personal Data Protection (DPDP) Practical Approach For CISOs
Digital Personal Data Protection (DPDP) Practical Approach For CISOs
Priyanka Aash103 views
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda... by ShapeBlue
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
ShapeBlue93 views
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue by ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlueWhat’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
ShapeBlue191 views
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading... by The Digital Insurer
Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading...
Import Export Virtual Machine for KVM Hypervisor - Ayush Pandey - University ... by ShapeBlue
Import Export Virtual Machine for KVM Hypervisor - Ayush Pandey - University ...Import Export Virtual Machine for KVM Hypervisor - Ayush Pandey - University ...
Import Export Virtual Machine for KVM Hypervisor - Ayush Pandey - University ...
ShapeBlue48 views
"Surviving highload with Node.js", Andrii Shumada by Fwdays
"Surviving highload with Node.js", Andrii Shumada "Surviving highload with Node.js", Andrii Shumada
"Surviving highload with Node.js", Andrii Shumada
Fwdays49 views
Data Integrity for Banking and Financial Services by Precisely
Data Integrity for Banking and Financial ServicesData Integrity for Banking and Financial Services
Data Integrity for Banking and Financial Services
Precisely76 views
State of the Union - Rohit Yadav - Apache CloudStack by ShapeBlue
State of the Union - Rohit Yadav - Apache CloudStackState of the Union - Rohit Yadav - Apache CloudStack
State of the Union - Rohit Yadav - Apache CloudStack
ShapeBlue218 views
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue by ShapeBlue
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue
ShapeBlue75 views
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit... by ShapeBlue
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...
ShapeBlue86 views
The Power of Heat Decarbonisation Plans in the Built Environment by IES VE
The Power of Heat Decarbonisation Plans in the Built EnvironmentThe Power of Heat Decarbonisation Plans in the Built Environment
The Power of Heat Decarbonisation Plans in the Built Environment
IES VE67 views
NTGapps NTG LowCode Platform by Mustafa Kuğu
NTGapps NTG LowCode Platform NTGapps NTG LowCode Platform
NTGapps NTG LowCode Platform
Mustafa Kuğu287 views

Tame Cloud Complex with F# powered DSLs