KEMBAR78
Rx workshop | PPTX
Reactive ExtensionsWorkshopRyan Riley & Wes Dyer
Logistics30 minute sections10 minutes presentation10 minutes coding10 minutes discussionNew partner every sectionPrizes for best code during each section
Where can I get them?Install with NuGetDownload at MSDN Data Developer Center
OutlineIntroduction to RxA Unified Programming ModelThe Power of RxRxJSSchedulersEvent ProcessingReactive CoincidenceContinuations EverywhereProgramming the Cloud
introduction to rxlike events but much better
The Reactive ExtensionsRx is …a set of types representing asynchronous data streamsa set of operators to query asynchronous data streamsa set of types to parameterize concurrencyRx = Observables + LINQ + Schedulers
Reactive ProgrammingIn computing, reactive programming is a programming paradigm oriented around data flows and the propagation of change.http://en.wikipedia.org/wiki/Reactive_programming
Why should I care?GPSRSS      feedsStock tickersSocialmediaUI eventsServer management
Reactive Programming using EventsDeclareeventAction<int> E;PublishE(42);Subscribe	E += x => Console.WriteLine(x);
Reactive Programming using RxDeclareISubject<int> S = newSubject<int>();PublishS.OnNext(42);SubscribeS.Subscribe(x => Console.WriteLine(x));
The Reactive ExtensionsRx is …a set of types representing asynchronous data streamsa set of operators to query asynchronous data streamsa set of types to parameterize concurrencyRx = Observables + LINQ + Schedulers
classProgram {ISubject<int> S = newSubject<int>();static void Main() {var p = newProgram();p.S.Subscribe(x => Console.WriteLine(x));p.S.OnNext(1);p.S.OnNext(2);p.S.OnNext(3);  }}classProgram {eventAction<int> E;static void Main() {var p = newProgram();p.E += x => Console.WriteLine(x);p.E(1);p.E(2);p.E(3); }}A Little Example
Separate Publish from Subscribe BothPublishSubscribe
First-Class “Events”An object is first-class when it:can be stored in variables and data structurescan be passed as a parameter to a subroutinecan be returned as the result of a subroutinecan be constructed at runtimehas intrinsic identity (independent of any given name)http://en.wikipedia.org/wiki/First-class_object
First-Class “Events”// storedIObservable<string> textChanged = …;// passedvoidProcessRequests(IObservable<string> input) {…}// returnedIObservable<int> QueryServer() {…}
PunctuationclassIObserver<in T>{voidOnNext(T value);voidOnError(Exception error);voidOnCompleted();}
ContractGrammar: OnNext* [OnCompleted | OnError]Serialized execution of observer’s methods01201120012
Challenge: Simple TransformationImplement Events.LengthChangedImplementObservables.LengthChangedOutput should be:
AnswerEventsObservables
Bridging from the Existing Worldquery asynchronous data streams
The Reactive ExtensionsRx is …a set of types representing asynchronous data streamsa set of operators to query asynchronous data streamsa set of types to parameterize concurrencyRx = Observables + LINQ + Schedulers
Empty// complete immediatelyObservable.Empty<int>();
Return// return 1 valueObservable.Return(1);1
Throw// throw an exceptionObservable.Throw(newException());
Never// never completeObservable.Never<int>();
Range// return three values starting with 0Observable.Range(0, 3);120
ToEnumerable / ToObservable// enumerable to observableEnumerable.Range(0, 3).ToObservable();// observable to enumerableObservable.Range(0, 3).ToEnumerable();120
Generate// observable for loopObservable.Generate(    0,   i => i < 3,    i => i + 1,   i => i * i);140
Create// anything you pleaseObservable.Create<int>(observer =>{IDisposableb = newBooleanDisposable();    newThread(() =>   {for (inti = 0; i < 3&& !b.IsDisposed; ++i)observer.OnNext(i);observer.OnCompleted();        return () => {};    }).Start();    returnb;});140
classProgram {  static void Main() {    Labellbl = newLabel();Formfrm = newForm {     Controls = { lbl}   };frm.MouseMove+= (s, args) => {};  }}classProgram {  static void Main() {Labellbl = newLabel();Formfrm = newForm {      Controls = { lbl }};varmouseMoves= Observable.FromEventPattern<MouseEventHandler,MouseEventArgs>(       x => frm.MouseMove += x,       x => frm.MouseMove -= x);mouseMoves.Subscribe(evt => {});  }}Using Events
classProgram {  static void Main() {    Labellbl = newLabel();Formfrm = newForm {     Controls = { lbl}   };frm.MouseMove+= (sender, args) =>   {      if(args.Location.X==args.Location.Y)     {lbl.Text =args.Location.ToString();      }    };Application.Run(frm);  }}classProgram {  static void Main() {Labellbl = newLabel();Formfrm = newForm {      Controls = { lbl }};varmouseUps = …;varmouseMoves= …;varspecificMoves =      fromup inmouseUps      frommove inmouseMoves      letlocation = move.EventArgs.Location      wherelocation.X == location.Y      selectnew { location.X, location.Y };    using(specificMoves   .Subscribe(evt => lbl.Text= evt.ToString()))    {Application.Run(frm);    }  }}LINQ to Events
ChallengeComplete DictionarySuggestCreate an Observable from the TextChangedevent
Create an Observable from an asynchronous web request
Combine these two observables to react to text input changes to return web service resultsAnswer
The Power of Rxtaking control
Monitoring// anything you pleasevar input = Observable    .FromEventPattern(txt, "TextChanged")    .Select(evt => ((TextBox)evt.Sender).Text)    .Timestamp()    .Do((Timestamped<string> evt) => Console.WriteLine(evt))    .Select(evt => evt.Value)    .Where(evt => evt.Length > 4)    .Do(evt => Console.WriteLine(evt));
Too Many Events
Duplication
Race Condition
ChallengeFind and apply the operators to fix these issues in DictionarySuggest
Answer
JavaScript
ChallengePort DictionarySuggest to RxJS
Answer
Schedulersparameterizing concurrency
The Reactive ExtensionsRx is …a set of types representing asynchronous data streamsa set of operators to query asynchronous data streamsa set of types to parameterize concurrencyRx = Observables + LINQ + Schedulers
Parameterizing ConcurrencyObservable.Timer(TimeSpan.FromSeconds(5))Which timer?System.Threading.Timer?System.Timers.Timer?System.Windows.Forms.Timer?System.Windows.Threading.Timer?Sleep on the current thread?… ?
Scheduler Abstractionexecution contextclockexecution policy
Scheduler InterfaceinterfaceIScheduler{DateTimeOffset Now { get; }IDisposable Schedule(Action work);IDisposable Schedule(TimeSpandueTime, Action work);IDisposable Schedule(DateTimeOffsetdueTime, Action work);}
Operational LayeringOperatorsvarxs = Observable.Range(1, 10, Scheduler.ThreadPool);var q = from x inxswhere x % 2 == 0select -x;q.Subscribe(Console.WriteLine);
Operational LayeringOperatorsObservablesvarxs = newRangeObservable<int>(1, 10, Scheduler.ThreadPool);var q = newSelectObservable<int>(newWhereObservable<int>(xs,   x => x % 2 == 0), x => -x);q.Subscribe(  newLambdaObserver<int>(Console.WriteLine));
Operational LayeringOperatorsObservablesvar n = 0;Scheduler.ThreadPool.Schedule(self => {if (n < 10) {   if ((n + 1) % 2 == 0)Console.WriteLine(-(n + 1));   n++;   self();  }});Schedulers
Operational LayeringOperatorsObservablesvar n = 0;Action<object> work = null;work = _ =>{if (n < 10) {   if ((n + 1) % 2 == 0)Console.WriteLine(-(n + 1));   n++;ThreadPool.QueueUserWorkItem(null, work); }};ThreadPool.QueueUserWorkItem(null, work);SchedulersNative Concurrency
One Interface to Rule Them All
The Problem of TimeOperations can take a long timeObservable.Timer(TimeSpan.FromYears(1000))
Some operators have time-based semanticsObservable.Timer(TimeSpan.FromSeconds(1)) .Buffer(TimeSpan.FromSeconds(1))The Problem of Time604512301423561s1s1s1s1s1s1s1s1s1s1s1s1s1s
When testing reactive programs, time is the problem.…virtual time is the solution.The Problem of Time
Schedulers Revisited
TestScheduler scheduler = newTestScheduler();IObservable<string> input = scheduler.CreateObservable(OnNext(300, “wes”),OnNext(400, “ryan”),OnCompleted(500));var results = scheduler.Run(() =>input.Select(x => x.Length));results.AssertEqual(OnNext(300, 3),OnNext(400, 4),OnCompleted(500));Unit Testing with Schedulers
Implement MainForm.GetQuotesImplementMainForm.GetQueryChallenge: Historical Data
Answer
event processingthe power of LINQ
The Reactive ExtensionsRx is …a set of types representing asynchronous data streamsa set of operators to query asynchronous data streamsa set of types to parameterize concurrencyRx = Observables + LINQ + Schedulers
Given: Stream of stock ticksFind: 10% daily price increaseEvent Processing
WindowingMSFT30.73MSFT27.01MSFT27.96INTC21.75MSFT31.21INTC22.54INTC20.98Group by symbol: GroupBy(t => t.Symbol)
AggregationMSFTINTC30.7327.0127.9631.2121.7522.5420.98Aggregate each day with previous day: Buffer(2, 1)
FilteringMSFTINTC31.2130.7327.0127.9627.9631.2121.7522.5422.5420.98Filter by price increase > 10%: Where(w => PriceIncrease(w) > .1)
ReduceMSFTINTC27.9631.21Reduce to a single stream: Merge()
Done!27.9631.21
from tick instockTicksgroup tick bytick.SymbolintosymbolStreamfrom window insymbolStream.Buffer(2, 1)let increase = PriceIncrease(window)where increase > .1select new { symbol = symbolStream.Key, increase }; LINQ: Event Processingsourcegroupaggregateapplyfilterreduce
Change MainForm.Query to compute the Average High and Average Low over the past 5 trading days as well as the current Close and DateChallenge: Event Processing
Answer
Reactive coincidencestreaming windows
The Reactive ExtensionsRx is …a set of types representing asynchronous data streamsa set of operators to query asynchronous data streamsa set of types to parameterize concurrencyRx = Observables + LINQ + Schedulers
Event Duration021vs021
An Exampleleft leftright
Representing DurationbeginbeginendendWindow
Store
Reactive CoincidenceWhich people are at the store while it is opened?5/55/6curleymoelarry
Reactive CoincidenceWhich people are at the store while it is opened?5/55/6moelarrycurleymoe
LINQ Joinfrom opening instoreOpeningsjoin person inpersonArrivesonopening.Closeequalsperson.Leavesinto gselectnew { opening.Day, People = g };
Change query in MainForm.MainForm to compute a stream of deltas when the mouse is downChallenge: Drag and Drop
Answer
Programming the clouda glimpse into the future
The Reactive ExtensionsRx is …a set of types representing asynchronous data streamsa set of operators to query asynchronous data streamsa set of types to parameterize concurrencyRx = Observables + LINQ + Schedulers
Distributed QueriesCloudresultsquery
Observable.Timer(TimeSpan.FromSeconds(1),Scheduler.Azure) .ObserveLocally() .Subscribe(Console.WriteLine);Distributed QueriesSend the query to the cloudSend the results back
Pass-by-Value	[Serializable] classMyType { … }Pass-by-ReferenceclassMyType : MarshalByRefObject{ … }Distributed Parameters
var x = 42;scheduler.Schedule(() =>Console.WriteLine(x));classClosure {public intx;public void M() {Console.WriteLine(x); }}var closure = newClosure();closure.x = 42;scheduler.Schedule(closure.M);Distributed SchedulingPass by value or reference?
interfaceIScheduler { …IDisposable Schedule<T>(T state, Action<T> work); …}Scheduler Interface Revisited
var x = 42;scheduler.Schedule( x, state =>Console.WriteLine(state));static void M(int state) {Console.WriteLine(state);}varx = 42;scheduler.Schedule( x, M);Distributed SchedulingNo closures!!!
scheduler.Schedule(42, x =>scheduler.Schedule(x + 1, y =>Console.WriteLine(y)));Nested Scheduling
Distributed SchedulingcloudScheduler
interfaceIScheduler { …IDisposable Schedule<T>(T state,   Action<IScheduler, T> work); …}Scheduler Interface Rerevisited
scheduler.Schedule(42, (s, x) =>s.Schedule(x + 1, y =>Console.WriteLine(y)));Nested Scheduling
Fan-out SchedulingSchedulerSchedulerSchedulerSchedulerSchedulerSchedulerScheduler
var d = scheduler.Schedule(42, (s, x) => {var d1 = s.Schedule(x + 1, Console.WriteLine);var d2 = s.Schedule(x + 2, Console.WriteLine);});Fan-out SchedulingHow do we make d depend on d1 & d2?
interfaceIScheduler { …IDisposable Schedule<T>(T state,Func<IScheduler, T, IDisposable> work); …}Scheduler Interface Rererevisited
var d = scheduler.Schedule(42, (s, x) => {var d1 = s.Schedule(x + 1, Console.WriteLine);vard2 = s.Schedule(x + 2, Console.WriteLine);  return newCompositeDisposable(d1, d2);});Fan-out Scheduling
scheduler.Schedule(42, (state, self) => {Console.WriteLine(state);   self(state + 1);  });Easy Recursive Scheduling
Change Program.Main to use the AppDomainSchedulerReimplementGenerateObservable.SubscribeChallenge: AppDomains
Answer
Continuations Everywherecontinuation-passing style used elsewhere
Ruby1..10.each do |x|    puts x * xend
AJAX$.ajax({	url: 'http://en.wikipedia.org/w/api.php',dataType: 'jsonp',data: {		action: 'opensearch',		search: term,		format: 'json'	},success: function(msg) {	alert('Data saved:' + msg);}});
node.jsvar net = require('net');var server = net.createServer(function (socket) {socket.write("Echo server\r\n"); 	socket.pipe(socket);});server.listen(1337, "127.0.0.1");
ChallengeUsing Rx, build a TCP server that works in a similar manner to node.js.
The Reactive ExtensionsRx is …a set of types representing asynchronous data streamsa set of operators to query asynchronous data streamsa set of types to parameterize concurrencyRx = Observables + LINQ + Schedulers

Rx workshop

Editor's Notes

  • #18 Guaranteed sequential or
  • #19 Does the code correctly add/remove multiple handlers?Is the code thread-safe?Can the code be refactored into a method?Can the code be generalized?
  • #42 Discuss: Using Rx for web clients – same library with an Rx prefix, library integrationDemo: run through demos from the Bridging from the Existing World sectionDemo: jQuery integrationImage from http://www.skorks.com/wp-content/uploads/2010/04/javascript.jpg
  • #60 How did you create an observablein GetQuotes?Did GetQuotes have any specific knowledge of what type of scheduler it uses?Did Query have any specific knowledge of how the observable it uses was produced?Why can we return IObservable&lt;object&gt; from Query?What does MyHistoricalScheduler.Run do?Ext.BindToChart contains an operator called ObserveOn, what does this do? What happens if we remove it?
  • #71 Were you able to reuse most of your previous code?Could you create more complex queries from the results of your new query?What would you do if you wanted to capture the last 5 days and not the last 5 trading days?What really is the power of LINQ?
  • #82 Which event has a duration?Which event stream defines the windows?Which event stream defines the data?Can an event stream without duration define the windows?Given a stream of points how can we compute deltas?Did you consider the initial point where the mouse button was clicked?
  • #101 What are the two basic parameter passing mechanisms in distributed systems? How are they indicated?Why don’t closures work in distributed systems?Regarding the scheduler interface…Why is the state passed in?Why is a disposable returned by the func?Why is there a scheduler argument in the func?
  • #105 Demo: jQuery.ajax function with callbacks