SlideShare uma empresa Scribd logo
1 de 60
Baixar para ler offline
ZIO Queue John A. De Goes — @jdegoes - http://degoes.net ScalaWave 2018
ZIO Queue
ScalaWave 2018 - Gdańsk, Poland
John A. De Goes
@jdegoes - http://degoes.net
What is ZIO?
Powered by Queues
Troubled Queues
Introducing ZIO Queue
Wrap Up
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
ZIO
ZIO lets you build
high-performance, type-safe,
concurrent, asynchronous
applications that don’t leak
resources or deadlock, and are
easy to reason about
compositionally, test, and refactor.
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
github.com/scalaz/scalaz-zio
ZIO
def main: Unit = {
println("Hello, what is your name?")
val name = readLine()
println(s"Good morning, $name!")
}
Second-Class Effects
✗ Pass to functions
✗ Return from functions
✗ Store in data structures
✗ Async/sync/concurrency
✓ Resource-safety
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
def main: IO[IOException, Unit] = for {
_ <- putStrLn("Hello, what is your name?")
name <- getStrLn
_ <- putStrLn(s"Good morning, $name!")
} yield ()
First-Class Effects
✓ Pass to functions
✓ Return from functions
✓ Store in data structures
✓ Async/sync/concurrency
✓ Resource-safety
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
IO[E, A]
IO[E, A] is an immutable value that
describes an effectful computation,
which may fail with a value of type E, or
compute a value of type A.
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
def runInParallel[E, A, B](
leftIO : IO[E, A],
rightIO: IO[E, B]): IO[E, (A, B)] =
for {
leftFiber <- leftIO.fork
rightFiber <- rightIO.fork
a <- leftFiber.join
b <- rightFiber.join
} yield (a, b)
Fork/Join Concurrency with Fibers
✓ Massive scalability over threads
✓ Non-blocking
✓ Automatically interruptible
✓ Always resource-safe
✓ Powerful composition
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Powered by Queues
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Producer Consumer
offer take
Queue
1-to-1
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Producer
Consumer
offer take
Queue
Producer
n-to-1
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Producer
Consumer
offer take
Queue
Consumer
1-to-m
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Consumer
offer take
Queue
Consumer
Producer
Producer
n-to-m
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
FIFO
LIFO
PRIO
Bounded
Unbounded
Dropping
Sliding
dimensions of variation
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
queue
actors
send
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
concurrent graph search
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
resource sharing
scarce resource
e.g. threads
Thread 1
take Thread 2offer
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
loose coupling
offer
take
Fast Producers
Slow Consumers
buffer
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Troubled Queues
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
java.util.concurrent.BlockingQueue
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
java.util.concurrent.BlockingQueue
trait BlockingQueue[A] {
def take: A
def offer(a: A): Boolean
}
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
java.util.concurrent.BlockingQueue
Blocks one thread
until element added
trait BlockingQueue[A] {
def take: A
def offer(a: A): Boolean
}
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
java.util.concurrent.BlockingQueue
Fast Producer Slow Consumer
offer take
Queue
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
java.util.concurrent.BlockingQueue
Fast Producer Slow Consumer
offer
take
Queue
manual
backpressure
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
java.util.concurrent.BlockingQueue
def fastProducer = {
if (!queue.offer(a)) {
// Slow down!!!
} else {
// Keep producing...
}
}
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
java.util.concurrent.BlockingQueue
Fast Producer Slow Consumer
offer
take
Queue
manual
backpressure
manual
backpressure
take
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
java.util.concurrent.ConcurrentLinkedQueue
trait ConcurrentLinkedQueue[A] {
def poll: A
def offer(a: A): Boolean
}
Returns null if empty
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
java.util.concurrent.ConcurrentLinkedQueue
Fast Producer Slow Consumer
offer poll
Queue
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
github.com/scalaz/scalaz-zio
ZIO QUEUE
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
ZIO Queue
trait Queue[A] {
def take: IO[Nothing, A]
def offer(a: A): IO[Nothing, Unit]
def shutdown(ts: Throwable*): IO[Nothing, Unit]
}
object Queue {
def bounded[A](capacity: Int): IO[Nothing, Queue[A]] = ???
def unbounded[A]: IO[Nothing, Queue[A]] = ???
}
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Example
for {
queue <- Queue.unbounded[String]
_ <- queue.offer("Give me Coffee!").forever.fork
_ <- queue.take.flatMap(putStrLn).forever
} yield ()
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
5. Concurrent
Consumer
offer take
Queue
Consumer
Producer
Producer
ZIO
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
4. Interruptible
for {
queue <- Queue.unbounded[String]
fiber <- queue.offer("Give me Coffee!").forever.fork
_ <- fiber.interrupt
} yield ()
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
3. Clean Shutdown
for {
queue <- Queue.unbounded[String]
fiber1 <- queue.offer("Give me Coffee!").forever.fork
fiber2 <- queue.take.forever.fork
_ <- queue.shutdown
} yield ()
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
2. Asynchronous
for {
queue <- Queue.unbounded[String]
worker = queue.take.flatMap(putStrLn).forever
workers10k = List.fill(10000)(worker)
_ <- IO.forkAll(workers10k)
_ <- queue.offer("More Coffee!").forever.fork
} yield ()
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
2. Asynchronous
trait BlockingQueue[A] {
def take: A ;
def offer(a: A): Boolean
}
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
1. Composable Backpressure
for {
queue <- Queue.bounded[String](10)
worker = queue.offer("Coffee").forever
workers10k = List.fill(10000)(worker)
_ <- IO.forkAll(workers10k)
_ <- queue.take.flatMap(putStrLn).forever.fork
} yield ()
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
case class Actor[+E, -A, +B](run: A => IO[E, B]) { self =>
def ! (a: A): IO[E, B] = run(a)
}
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]):
IO[Nothing, Actor[E, A, B]] =
for {
state <- Ref(s)
queue <- Queue.bounded[(A, Promise[E, B])](QueueSize)
fiber <- (for {
t <- queue.take
s <- state.get
(a, promise) = t
receiver = receive(s, a)
completer = (s: S, b: B) =>
state.set(s) *> promise.complete(b)
_ <- receiver.redeem(
e => supervise(receiver, e)
.redeem(promise.error, completer), completer)
} yield ()).forever.fork
} yield Actor[E, A, B]((a: A) =>
Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Application: Scalaz Actors
def makeCounter: IO[Nothing, Actor[Nothing, Int, Int]] =
makeActor(Supervisor.logDefects(Logging))(0) {
(state: Int, n: Int) =>
IO.now((state + n, state + n))
}
for {
counter <- makeCounter
_ <- counter ! 40
_ <- counter ! -2
v <- counter ! 0
} yield v
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
WRAP UP
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
github.com/scalaz/scalaz-zio
ZIO CFC
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
ZIO ROADMAP
Performance Sliding Dropping
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
https://gitter.im/scalaz/scalaz/
https://gitter.im/scalaz/scalaz-ioqueue/
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
Functional Scala by John A. De Goes
Local Remote Date
Scotland European Time Sep 10 - 14
Toronto East Coast Time Oct 1 - 5
? European Time Oct 22 - 26
SF / SV Pacific Coast Time Nov 18 -
22
What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
THANK YOU!
@jdegoes - http://degoes.net

Mais conteúdo relacionado

Mais procurados

Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Philip Schwarz
 
Boost your productivity with Scala tooling!
Boost your productivity  with Scala tooling!Boost your productivity  with Scala tooling!
Boost your productivity with Scala tooling!MeriamLachkar1
 
ZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaWiem Zine Elabidine
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayDebasish Ghosh
 
A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOJorge Vásquez
 
The Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldThe Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldPhilip Schwarz
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Philip Schwarz
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type ClassesJohn De Goes
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...Philip Schwarz
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Philip Schwarz
 
Izumi 1.0: Your Next Scala Stack
Izumi 1.0: Your Next Scala StackIzumi 1.0: Your Next Scala Stack
Izumi 1.0: Your Next Scala Stack7mind
 
Ad hoc Polymorphism using Type Classes and Cats
Ad hoc Polymorphism using Type Classes and CatsAd hoc Polymorphism using Type Classes and Cats
Ad hoc Polymorphism using Type Classes and CatsPhilip Schwarz
 
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021Natan Silnitsky
 
The Uniform Access Principle
The Uniform Access PrincipleThe Uniform Access Principle
The Uniform Access PrinciplePhilip Schwarz
 
Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!Jorge Vásquez
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsPhilip Schwarz
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8LivePerson
 

Mais procurados (20)

Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
 
Zio in real world
Zio in real worldZio in real world
Zio in real world
 
Boost your productivity with Scala tooling!
Boost your productivity  with Scala tooling!Boost your productivity  with Scala tooling!
Boost your productivity with Scala tooling!
 
Applicative style programming
Applicative style programmingApplicative style programming
Applicative style programming
 
ZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in ScalaZIO: Powerful and Principled Functional Programming in Scala
ZIO: Powerful and Principled Functional Programming in Scala
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
 
A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIO
 
The Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldThe Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and Fold
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
 
Izumi 1.0: Your Next Scala Stack
Izumi 1.0: Your Next Scala StackIzumi 1.0: Your Next Scala Stack
Izumi 1.0: Your Next Scala Stack
 
Applicative Functor
Applicative FunctorApplicative Functor
Applicative Functor
 
Ad hoc Polymorphism using Type Classes and Cats
Ad hoc Polymorphism using Type Classes and CatsAd hoc Polymorphism using Type Classes and Cats
Ad hoc Polymorphism using Type Classes and Cats
 
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
How to successfully manage a ZIO fiber’s lifecycle - Functional Scala 2021
 
The Uniform Access Principle
The Uniform Access PrincipleThe Uniform Access Principle
The Uniform Access Principle
 
Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
 

Semelhante a ZIO Queue

ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingJohn De Goes
 
Environmental effects - a ray tracing exercise
Environmental effects - a ray tracing exerciseEnvironmental effects - a ray tracing exercise
Environmental effects - a ray tracing exercisePierangelo Cecchetto
 
The Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect SystemThe Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect SystemJohn De Goes
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadOliver Daff
 
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative LanguagesJavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative LanguagesStephen Chin
 
The report of JavaOne2011 about groovy
The report of JavaOne2011 about groovyThe report of JavaOne2011 about groovy
The report of JavaOne2011 about groovyYasuharu Nakano
 
Scala meetup
Scala meetupScala meetup
Scala meetup扬 明
 
The What, Why And How of ClojureScript
The What, Why And How of ClojureScriptThe What, Why And How of ClojureScript
The What, Why And How of ClojureScriptIvan Bokii
 
Python concurrency: libraries overview
Python concurrency: libraries overviewPython concurrency: libraries overview
Python concurrency: libraries overviewAndrii Mishkovskyi
 
Orchestrated Chaos: Applying Failure Testing Research at Scale.
Orchestrated Chaos: Applying Failure Testing Research at Scale.Orchestrated Chaos: Applying Failure Testing Research at Scale.
Orchestrated Chaos: Applying Failure Testing Research at Scale.Reactivesummit
 
Advanced Python, Part 2
Advanced Python, Part 2Advanced Python, Part 2
Advanced Python, Part 2Zaar Hai
 
"Elixir of Life" - Dev In Santos
"Elixir of Life" - Dev In Santos"Elixir of Life" - Dev In Santos
"Elixir of Life" - Dev In SantosFabio Akita
 
Zope component architechture
Zope component architechtureZope component architechture
Zope component architechtureAnatoly Bubenkov
 
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...Stephen Chin
 
Julio Capote, Twitter
Julio Capote, TwitterJulio Capote, Twitter
Julio Capote, TwitterOntico
 

Semelhante a ZIO Queue (20)

ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
 
Fiber supervision in ZIO
Fiber supervision in ZIOFiber supervision in ZIO
Fiber supervision in ZIO
 
Environmental effects - a ray tracing exercise
Environmental effects - a ray tracing exerciseEnvironmental effects - a ray tracing exercise
Environmental effects - a ray tracing exercise
 
Ray tracing with ZIO-ZLayer
Ray tracing with ZIO-ZLayerRay tracing with ZIO-ZLayer
Ray tracing with ZIO-ZLayer
 
The Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect SystemThe Design of the Scalaz 8 Effect System
The Design of the Scalaz 8 Effect System
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
 
Berlin meetup
Berlin meetupBerlin meetup
Berlin meetup
 
Clojure And Swing
Clojure And SwingClojure And Swing
Clojure And Swing
 
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative LanguagesJavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
 
The report of JavaOne2011 about groovy
The report of JavaOne2011 about groovyThe report of JavaOne2011 about groovy
The report of JavaOne2011 about groovy
 
Scala meetup
Scala meetupScala meetup
Scala meetup
 
The What, Why And How of ClojureScript
The What, Why And How of ClojureScriptThe What, Why And How of ClojureScript
The What, Why And How of ClojureScript
 
Python concurrency: libraries overview
Python concurrency: libraries overviewPython concurrency: libraries overview
Python concurrency: libraries overview
 
Orchestrated Chaos: Applying Failure Testing Research at Scale.
Orchestrated Chaos: Applying Failure Testing Research at Scale.Orchestrated Chaos: Applying Failure Testing Research at Scale.
Orchestrated Chaos: Applying Failure Testing Research at Scale.
 
Advanced Python, Part 2
Advanced Python, Part 2Advanced Python, Part 2
Advanced Python, Part 2
 
"Elixir of Life" - Dev In Santos
"Elixir of Life" - Dev In Santos"Elixir of Life" - Dev In Santos
"Elixir of Life" - Dev In Santos
 
Zope component architechture
Zope component architechtureZope component architechture
Zope component architechture
 
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
 
Zio from Home
Zio from Home Zio from Home
Zio from Home
 
Julio Capote, Twitter
Julio Capote, TwitterJulio Capote, Twitter
Julio Capote, Twitter
 

Mais de John De Goes

One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them AllJohn De Goes
 
Error Management: Future vs ZIO
Error Management: Future vs ZIOError Management: Future vs ZIO
Error Management: Future vs ZIOJohn De Goes
 
Atomically { Delete Your Actors }
Atomically { Delete Your Actors }Atomically { Delete Your Actors }
Atomically { Delete Your Actors }John De Goes
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final TaglessJohn De Goes
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: RebirthJohn De Goes
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: RebirthJohn De Goes
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018John De Goes
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New GameJohn De Goes
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsJohn De Goes
 
Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional ArchitectureJohn De Goes
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsJohn De Goes
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free MonadsJohn De Goes
 
Streams for (Co)Free!
Streams for (Co)Free!Streams for (Co)Free!
Streams for (Co)Free!John De Goes
 
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...John De Goes
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and FutureJohn De Goes
 
All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!John De Goes
 
Getting Started with PureScript
Getting Started with PureScriptGetting Started with PureScript
Getting Started with PureScriptJohn De Goes
 
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual AnalyticsSlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual AnalyticsJohn De Goes
 
The Next Great Functional Programming Language
The Next Great Functional Programming LanguageThe Next Great Functional Programming Language
The Next Great Functional Programming LanguageJohn De Goes
 

Mais de John De Goes (20)

One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
 
Error Management: Future vs ZIO
Error Management: Future vs ZIOError Management: Future vs ZIO
Error Management: Future vs ZIO
 
Atomically { Delete Your Actors }
Atomically { Delete Your Actors }Atomically { Delete Your Actors }
Atomically { Delete Your Actors }
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final Tagless
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: Rebirth
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: Rebirth
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New Game
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka Actors
 
Orthogonal Functional Architecture
Orthogonal Functional ArchitectureOrthogonal Functional Architecture
Orthogonal Functional Architecture
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free Monads
 
Streams for (Co)Free!
Streams for (Co)Free!Streams for (Co)Free!
Streams for (Co)Free!
 
MTL Versus Free
MTL Versus FreeMTL Versus Free
MTL Versus Free
 
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and Future
 
All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!
 
Getting Started with PureScript
Getting Started with PureScriptGetting Started with PureScript
Getting Started with PureScript
 
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual AnalyticsSlamData - How MongoDB Is Powering a Revolution in Visual Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
 
The Next Great Functional Programming Language
The Next Great Functional Programming LanguageThe Next Great Functional Programming Language
The Next Great Functional Programming Language
 

Último

The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 

Último (20)

The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 

ZIO Queue

  • 1. ZIO Queue John A. De Goes — @jdegoes - http://degoes.net ScalaWave 2018 ZIO Queue ScalaWave 2018 - Gdańsk, Poland John A. De Goes @jdegoes - http://degoes.net
  • 2. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
  • 3. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up ZIO ZIO lets you build high-performance, type-safe, concurrent, asynchronous applications that don’t leak resources or deadlock, and are easy to reason about compositionally, test, and refactor.
  • 4. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up github.com/scalaz/scalaz-zio ZIO
  • 5. def main: Unit = { println("Hello, what is your name?") val name = readLine() println(s"Good morning, $name!") } Second-Class Effects ✗ Pass to functions ✗ Return from functions ✗ Store in data structures ✗ Async/sync/concurrency ✓ Resource-safety What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
  • 6. def main: IO[IOException, Unit] = for { _ <- putStrLn("Hello, what is your name?") name <- getStrLn _ <- putStrLn(s"Good morning, $name!") } yield () First-Class Effects ✓ Pass to functions ✓ Return from functions ✓ Store in data structures ✓ Async/sync/concurrency ✓ Resource-safety What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
  • 7. IO[E, A] IO[E, A] is an immutable value that describes an effectful computation, which may fail with a value of type E, or compute a value of type A. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
  • 8. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
  • 9. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
  • 10. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
  • 11. def runInParallel[E, A, B]( leftIO : IO[E, A], rightIO: IO[E, B]): IO[E, (A, B)] = for { leftFiber <- leftIO.fork rightFiber <- rightIO.fork a <- leftFiber.join b <- rightFiber.join } yield (a, b) Fork/Join Concurrency with Fibers ✓ Massive scalability over threads ✓ Non-blocking ✓ Automatically interruptible ✓ Always resource-safe ✓ Powerful composition What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up
  • 12. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Powered by Queues
  • 13. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Producer Consumer offer take Queue 1-to-1
  • 14. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Producer Consumer offer take Queue Producer n-to-1
  • 15. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Producer Consumer offer take Queue Consumer 1-to-m
  • 16. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Consumer offer take Queue Consumer Producer Producer n-to-m
  • 17. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up FIFO LIFO PRIO Bounded Unbounded Dropping Sliding dimensions of variation
  • 18. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up queue actors send
  • 19. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up concurrent graph search
  • 20. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up resource sharing scarce resource e.g. threads Thread 1 take Thread 2offer
  • 21. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up loose coupling offer take Fast Producers Slow Consumers buffer
  • 22. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Troubled Queues
  • 23. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up java.util.concurrent.BlockingQueue
  • 24. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up java.util.concurrent.BlockingQueue trait BlockingQueue[A] { def take: A def offer(a: A): Boolean }
  • 25. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up java.util.concurrent.BlockingQueue Blocks one thread until element added trait BlockingQueue[A] { def take: A def offer(a: A): Boolean }
  • 26. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up java.util.concurrent.BlockingQueue Fast Producer Slow Consumer offer take Queue
  • 27. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up java.util.concurrent.BlockingQueue Fast Producer Slow Consumer offer take Queue manual backpressure
  • 28. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up java.util.concurrent.BlockingQueue def fastProducer = { if (!queue.offer(a)) { // Slow down!!! } else { // Keep producing... } }
  • 29. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up java.util.concurrent.BlockingQueue Fast Producer Slow Consumer offer take Queue manual backpressure manual backpressure take
  • 30. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up java.util.concurrent.ConcurrentLinkedQueue trait ConcurrentLinkedQueue[A] { def poll: A def offer(a: A): Boolean } Returns null if empty
  • 31. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up java.util.concurrent.ConcurrentLinkedQueue Fast Producer Slow Consumer offer poll Queue
  • 32. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up github.com/scalaz/scalaz-zio ZIO QUEUE
  • 33. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up ZIO Queue trait Queue[A] { def take: IO[Nothing, A] def offer(a: A): IO[Nothing, Unit] def shutdown(ts: Throwable*): IO[Nothing, Unit] } object Queue { def bounded[A](capacity: Int): IO[Nothing, Queue[A]] = ??? def unbounded[A]: IO[Nothing, Queue[A]] = ??? }
  • 34. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Example for { queue <- Queue.unbounded[String] _ <- queue.offer("Give me Coffee!").forever.fork _ <- queue.take.flatMap(putStrLn).forever } yield ()
  • 35. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up 5. Concurrent Consumer offer take Queue Consumer Producer Producer ZIO
  • 36. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up 4. Interruptible for { queue <- Queue.unbounded[String] fiber <- queue.offer("Give me Coffee!").forever.fork _ <- fiber.interrupt } yield ()
  • 37. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up 3. Clean Shutdown for { queue <- Queue.unbounded[String] fiber1 <- queue.offer("Give me Coffee!").forever.fork fiber2 <- queue.take.forever.fork _ <- queue.shutdown } yield ()
  • 38. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up 2. Asynchronous for { queue <- Queue.unbounded[String] worker = queue.take.flatMap(putStrLn).forever workers10k = List.fill(10000)(worker) _ <- IO.forkAll(workers10k) _ <- queue.offer("More Coffee!").forever.fork } yield ()
  • 39. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up 2. Asynchronous trait BlockingQueue[A] { def take: A ; def offer(a: A): Boolean }
  • 40. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up 1. Composable Backpressure for { queue <- Queue.bounded[String](10) worker = queue.offer("Coffee").forever workers10k = List.fill(10000)(worker) _ <- IO.forkAll(workers10k) _ <- queue.take.flatMap(putStrLn).forever.fork } yield ()
  • 41. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors case class Actor[+E, -A, +B](run: A => IO[E, B]) { self => def ! (a: A): IO[E, B] = run(a) }
  • 42. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 43. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 44. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 45. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 46. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 47. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 48. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 49. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 50. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 51. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 52. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 53. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeActor[S, E, A, B](supervisor: Supervisor)(s: S)(receive: (S, A) => IO[E, (S, B)]): IO[Nothing, Actor[E, A, B]] = for { state <- Ref(s) queue <- Queue.bounded[(A, Promise[E, B])](QueueSize) fiber <- (for { t <- queue.take s <- state.get (a, promise) = t receiver = receive(s, a) completer = (s: S, b: B) => state.set(s) *> promise.complete(b) _ <- receiver.redeem( e => supervise(receiver, e) .redeem(promise.error, completer), completer) } yield ()).forever.fork } yield Actor[E, A, B]((a: A) => Promise.make[E, B].flatMap(p => queue.offer((a, p)).flatMap(_ => p.get))
  • 54. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Application: Scalaz Actors def makeCounter: IO[Nothing, Actor[Nothing, Int, Int]] = makeActor(Supervisor.logDefects(Logging))(0) { (state: Int, n: Int) => IO.now((state + n, state + n)) } for { counter <- makeCounter _ <- counter ! 40 _ <- counter ! -2 v <- counter ! 0 } yield v
  • 55. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up WRAP UP
  • 56. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up github.com/scalaz/scalaz-zio ZIO CFC
  • 57. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up ZIO ROADMAP Performance Sliding Dropping
  • 58. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up https://gitter.im/scalaz/scalaz/ https://gitter.im/scalaz/scalaz-ioqueue/
  • 59. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up Functional Scala by John A. De Goes Local Remote Date Scotland European Time Sep 10 - 14 Toronto East Coast Time Oct 1 - 5 ? European Time Oct 22 - 26 SF / SV Pacific Coast Time Nov 18 - 22
  • 60. What is ZIO? Powered by Queues Troubled Queues Introducing ZIO Queue Wrap Up THANK YOU! @jdegoes - http://degoes.net