- AJ O’Neal (twitter github blog)
- Charles Max Wood (twitter github Teach Me To Code Rails Summer Camp)
- Jamison Dance (twitter github blog)
- Peter Cooper (twitter github blog)
- Yehuda Katz (twitter github blog)
- Synchronous functions vs Asynchronous functions
- XML/HTTP request (AJAX)
- User Event
- Game loops
- named functions vs anonymous functions
- scope problems
- web workers
- Node EventEmitter
- Node sync
- I/O async
- Your coffee shop doesn’t use two phase commits
- Threaded systems
- Idle time in browser
- onUnload hook
- Ad vendors
- Utah JS Call for Papers
- The Adventures of Merlin (Chuck)
- The Lean Startup (Yehuda)
- Sherlock (Peter)
- Fluent Conference (Peter)
- Reg Braithwaite (Peter)
- Crockford Videos (AJ)
- YUI Blog (AJ)
- Node Google Voice (AJ)
- 750words.com (Jamison)
- Working Effectively with Legacy Code (Jamison)
JAMISON: What’s Canada? No. Canada isn’t in between there.
PETER: It’s America’s hat.
AJ: That’s me. Yup.
CHUCK: So since we are new, do you want to just introduce yourself?
AJ: Okay sure. So, I work at SpotterRF (its radar company). But we get to do some good stuff with HTML5 and our browser-based software and some of our internal applications and a little bit of NodeJS as well.
CHUCK: All right. Also on our podcast we have Peter Cooper.
CHUCK: All right we also have Jamison Dance.
CHUCK: (Nepotism!) Oh wait never mind.
JAMISON: (A little bit of that.) I also dabble in machine learning and data mining natural language processing, that kind of stuff on the side so I do some of that for fun.
And I really kind of got to see the power behind it and thought it was a cool language but didn’t really get into it until people started talking about Node.js and stuff like that, decided have a second look and I really kind of dig it as the language. I’m getting more and more involved in community and I’m excited to see where it can go.
This week we were talking about asynchronous handling and the event loop in the browsers and AJ is kind of an expert on that so why don’t you go ahead and start a conversation and we’ll take it from there.
CHUCK: Alright. Are we talking about things like, what is it, setTimeout that you get in a browser? Or are we talking more about things like when you do an AJAX call and you have this success function blah blah blah and so it kind of sets up an event so that when it returns it calls that anonymous function.
AJ: Well yeah. I mean both of those kind of tied together same event loop.
I mean I think lots of people come from like C and Ruby and I don’t know, just stuff where each line of code happens and the next line of code happen.
AJ: Yeah I think that’s a great starting point. So yeah I’ve seen that a lot too where were people ask like, is this a synchronous function or an asynchronous function? Like when you start talking about something like for each or other methods that appear to take a callback and then people want to know, how do you know if it’s synchronous or asynchronous?
So a good definition for that would be that it is synchronous when you’re going to complete the function and everything inside of it, everything that you can visually see inside of that function before you return (or the function closes).
Whereas the asynchronous part is if you have something like a setTimeout or you have an XML/HTTP request or are you waiting for a user event, that you don’t know when it going to happen. Then when your function ends, you are returning “undefined” or perhaps you’re returning some type of emitter or call back handling object, right?
CHUCK: So what happens then if let’s say, I want when I hover over this icon, that it changes colors or whatever. What happens in that instance when I set that hover state up with jQuery or whatever?
AJ: So you’re attaching an event or a function, to the event handler and when you move the mouse, as long as nothing else processing, then you are going to see the mouse cursor move and then it’s going to fire an event for every pixel or however often it can handle firing the events. And then when the processor is free to handle that event, then will execute your function and carry out whatever had inside.
So you know, if we were to do something like in C code where you’re reading from the user’s input and also, (I forget what it is) but you know, you open standard and then you are going to read into it. Then your program halts, you sit there, you wait, you do nothing.
AJ: And you don’t want to do that in a browser. You want the hover event to fire you on, the visual display to change. And you wanna do all that within a single thread, so amateur; (more or less) programmers can do something without having immediate failures and confusion.
CHUCK: Alright so that makes sense. What are some of the things that people use it for. I mean we talk about hover states and things like that. Any other like major things that people—
JAMISON: I think the most common one is just HTTP request. So you’re just going to get some data from somewhere.
JAMISON: I mean like all the AJAX library and stuff like that. So that’s where they are all started because it’s going to take a while for it to come back off the network and then you might do something with it when it gets there but you don’t wanna block while you’re waiting.
CHUCK: Yeah, so you just set a callback for whenever somebody does something?
When you got the pyramid because you want to make a request to Facebook and when Facebook calls back with the log in then you wanna make a request to Amazon or you wanna make a requested to Twitter, they are somehow dependent. That’s when the waterfall is actually being used appropriately. If you can do two things at one time, then you should do them both at the same or rather put them both in the event loop at the same time.
It wasn’t until 2000 or 2001 that Microsoft added the XML/HTTP request. Is that right?
JAMISON: I think so. Yeah.
AJ: I don’t think was built with the idea that you would want to be doing so many asynchronous things in mind when it was first created. So there isn’t a built in way to say, oh, well this is a clear way to handle that solution. That’s kind of what led me to create the Futures JS library.
Just a quick rundown, so say you’ve got the waterfall, the way I like to do it, (the poor man’s way without even using a library or anything) , is simply to separate that waterfall into functions that are all indented at the same level. Then have that end of each function, the call to the next function. So when I look at my code, the very last thing to execute is all the way at the top and the very first thing to execute is all the way down at the bottom and every function calls the next. It’s a little bit nicer than the waterfall because you named functions (so hopefully you are naming them something useful rather than just having the anonymous functions nested further and further).
You can reduce scope problems that way, because there are problems that occur with scope, where you got the variable in one place and then you modify it in another place and it turns out that in that lower scope you might have done something two or three times and when you get to the next place where you are going to modify that variable, it was already modified. So that it’s a thread problem all over again. So if you keep your scopes as high as possible, you definitely have much less of a chance of running into that, has this variable been modified when I wasn’t thinking it would.
CHUCK: I’m trying to wrap my head around this. So basically what you’re saying is that, you, instead of having, let’s say that you have one event or you have one function that needs to be called, once two other functions have completed, what you set up is so that it just does it all insert certain sequence anyway? Or—
AJ: What I’m saying is, you have a sequence, instead of going through that, what you call Jamison, the death pyramid?
JAMISON: The Pyramid of Doom.
AJ: Okay, pyramid of doom. So instead of doing the pyramid of doom, where you’re indenting, indenting, indenting, indenting, anonymous function one after the other to the point that when you go back and look at your code, you cannot tell what it does anymore. You can just tell that it’s indented fifty spaces. That you keep all of those functions indented at the same level and give them proper names. And that helps just with the organization.
CHUCK: Oh I see. That makes sense.
So then what you do in your pyramid of doom, instead of it being indented, this is code readability issue right?
CHUCK: instead of indenting, you know, yeah, for each anonymous function that needs to be called within the other anonymous function, you just set up an event that calls back out to your list of possible functions that it can latch onto and execute based on the event that was fired.
AJ: Right, but if you want to do two things at the same time, the poor man’s way to do it is, to set a variable as a counter. Then for every function you have, you increment the counter by one, and then when all the functions are done, you have them all call the same callback.
AJ: So every time that call back gets called, it decrements the counter and then when the counter reaches zero, is when you call the final callback with inside of it, the data that has all of the outputs from the other functions. The two functions that I have implemented in futures for that. One is called “forEachAsynch”, which handles the waterfall or sequence they are both very similar and then I created a function called “join”, which does exactly what I just said. Every time you add a function, it increments and when they are all done, it decrements, then calls for a callback.
CHUCK: Interesting, I like it. So it’s kind of a workflow manager.
AJ: Yeah, definitely.
But one thing you want to be careful of, still understanding the difference between doing things sequentially on purpose and doing in things in parallel on purpose. Because you can do things sequentially on accident and just waste time,
AJ: But you can also do things in parallel and hog down the browser or even cause your application to start throwing errors. Because for example you can only do six in the latest browsers, you can only do I think six web requests at a time.
AJ: And so if you’re like oh, well these things don’t need to be sequential, so I’ll just go ahead and do them all at once. And you’ve got 20 requests you wanna make or something like that. So you have been queuing these up from user changes and now it’s time to push your memory database out to somewhere where it’s going to be saved, something like that.
Well if you queued up 20 of these Web requests, then when you are going to do them, only six of them are going to happen until those are done, the others are still waiting anyway and then you end up with the case where maybe you got HTTP time out and then you get an error for thrown when your code is perfectly valid. Makes sense?
AJ: You got to understand what it is that you want to do on purpose and what you want to do because it’s convenient and make sure that they are aligned and then that you’re not doing too many requests at once just because you can.
CHUCK: So are there any other areas that we run into logjams like this and in the browser or is the HTTP request kind of the only thing there?
AJ: I haven really worked much with the web workers or—
JAMISON: (yeah you should talk about that.)
AJ: WebSockets. How many of you have been working with either of those?
CHUCK: Not really, no.
AJ: When I first tried WebSockets, it was a while ago and it was kind of *** (00:17:15). So I haven’t played with it since. But I want to pick it back up in the next week or so. I got a little project I have to play with.
So in your web worker, you can compute some stuff and then pass the message back to the browser thread. Then in the browser, you listen on the web workers events. So if you had some computations that would take a long time, you could just spin up a web worker and then web worker would do it all and then submit the data back via a message that would fire an event in the browser.
CHUCK: That sounds really interesting I’ll have to look into that.
PETER: There’s also a fibers library for Node or similar type of thing and if you are in the Nodes side of things?
AJ: I thought fibers was to make it look less asynchronous or am I mistaken?
Peter: You can do use it to do that yes, but it can build on top of the extra stuff that will add threading support to Node. It uses threads to do it.
PETER: Can pass through reference to stuff though, because I’ve seen people use web workers to deal with, like sandbox implementations and you can pass through functions and references to things that you want the web worker to access. So, it’s kind of a sanitized environment which is kind of cool actually.
JAMISON: Yeah I think you can somewhat emulate that with an iframe as well. (I mean not that I’m suggesting that you use an iframe to do web worker’s job), but if you did need access to some of those other things, you didn’t want to do deal with that limitations of the web worker for very specific reasons.
CHUCK: that’s reduced (00:19:49).
CHUCK: (What were we talking about? Anyway. )
AJ: But in Node.js, the difference is the API is different and you have a lot more that you can do. But it’s still the same event loop. I use a lot of the Node libraries in the browser like the node EventEmitter is my primary emitter that I use in the browser because it’s a very, very good solution to a wide range of problems.
PETER: If you are on Node though, there is something that you can install called “node-sync”, which gives you that kind of being able to write asynchronous code in a very synchronous way for your gain. But that definitely, that’s won’t work with the browser. It digs into the Node runtime.
JAMISON: So why would you want to do that? That seems like you are using Node because it’s asynchronous and then making it synchronous again. Like why not just use synchronous?
PETER: You can write the code in synchronous style, but it will still run asynchronously, if you see what I mean. You wrap it in this big function call called synch and you pass in a function and then anything that’s in that function will run asynchronously even if something blocks, it won’t hold up in entire system.
JAMISON: So chuck you asked about when you want to do asynchronous stuff. We mention stuff in the browser but I mean if you are talking about Node then there’s all this kind of stuff too. Like talking the databases’ file systems and stuff and all of kinds of system calls and then there’s lots of opportunity for asynchronous things.
CHUCK: So that is an interesting point I think we all have experience with Ruby and Ruby generally doesn’t do I/O blocking. So if it’s doing some kind of I/O-like talking to a database or this or that, then it won’t block on that. It will just move on and then when it comes back, it will pick it up again.
So it that’s kind of the same thing here that we’re talking about then?
AJ: Well what do you mean by that? I because I thought that, I mean, I just used like the MySQL library with Ruby but it seemed like file reads and database access and what not in Ruby is blocking. Isn’t it?
JAMISON: Do you mean if you pass in blocks chuck?
CHUCK: My understanding is, let’s say, that you have (and I’m not a Ruby expert) I’m pretty proficient with Rails.
AJ: (Yehuda why did you leave us.)
CHUCK: Yeah Yehuda was supposed to be on. We are not sure where he is. We weren’t doing super well with the communication. So he might show up in like five minutes and say okay I’m here.
PETER: Come on chuck dig that hole.
CHUCK: So my understanding is that Ruby has some provision for not blocking on I/O and I don’t remember exactly how it works.
PETER: That’s Ruby 1.9?
JAMISON: I think that’s new.
CHUCK: But anyway, so it can make a request and then since its single threaded it can go and do some other work and then I’m not explaining this well at all.
PETER: I think what you are probably getting at is that if you do have multiple threads running in Ruby 1.9 and you do a kind of blocking I/O requests in one of those threads, it won’t cease the entire because of the global interpreter lock; it will allow the other threads to continue running.
PETER: But it has more threads it’s not all on a single thread. In that case it will just block if you make a blocking call.
JAMISON: So if you are using Ruby threads you mean?
PETER: Yes you have to using a Ruby thread.
PETER: But there is a real thread in 1.9 but it still hooked up with its global interpreter lock things.
CHUCK: Yeah that’s what it was and I’m sorry I didn’t communicate it well. I don’t completely understand the interworking’s of the VM so anyway, yeah I made myself sound like an idiot but that’s okay.
CHUCK: (But anyway so, yeah IO, asynchronous stuff). Are there any other examples of things that Node does that are asynchronous that aren’t call-outs the other systems?
AJ: Everything that you would do in C that blocks, now it doesn’t tell the network access all the file access, database access.
JAMISON: You can make non-blocking calls in C too right? You just can’t attach callback.
AJ: Its hacker complicated. Especially if you’re looking for cross platform approach. There are libraries like Libav, which Node used to use but, by yeah it’s not quite so elegant by any means.
PETER: So they turn to the dark side.
For example most of the APIs in Nodes have a synch option so there’s fs.read and there is fs.readsync, right? There are some things you cannot do that for. And then you end up having to mingle your code to add this callback as the last parameter. Or even worse like you have a callback and then you decide you need to add yet another parameter to a function.
So then you end up doing this guesswork where it’s like okay first argument exists and the second argument exists in the third argument isn’t a function but the fourth argument is, then that’s the callback in jQuery. I hate that. I was going to think you got to write with setTimeout where function comes first, I think it’s a very good model.
JAMISON: Yeah it’s built into the language. A really good read is (and I will give a link for this later) but there is an article “Your coffee shop doesn’t use two phase commits”. And it describes the event paradigm really well, they talking about databases but it really applies to events well.
You go to Starbucks, order a coffee pot the cocoa bean right and you order your coffee or your hot chocolate or whatever and then you go and sit down right, you pay and you sit down. They got the most important part of what they wanted, which is your money and what you want. Then you sit around and wait. it’s not like you go up and you say, okay I want a coffee and they say okay well just wait here in line and will take 45 seconds to get that to you and then serve the next customer, right?
PETER: (If only they did.)
CHUCK: Right so you don’t want to wind up in the paying queue and then not get in your food queue.
JAMISON: Well you kind of do end up with both of those queues but at separate times.
Did Yehuda come back?
CHUCK: Yeah I thought I heard him there for a second.
JAMISON: Everyone say hi Yehuda.
CHUCK: Dropped off.
JAMISON: I think he’s gone. Man, that California internet.
AJ: So I think I usually think about event systems, I think that the way the analogy given about the coffee shop is good. I think it’s it helps understand what event it is, but I think it misses the other options.
I think there is a class of people who think the event, the solutions are just basically the only way to get with concurrency and as people probably know, threaded systems actually worked out okay. I don’t really want to get into an analogy war. I don’t really wanna figure out what threads mean in terms of the coffee shop, but there’s definitely a fetishisation of events.
I think in UI environments they make a lot of sense, because almost everything that’s happening is responding to a thing that the user is doing. So like conceptually event when the user clicks, I would like to do this, but it’s not obvious just because it makes sense when we are talking about responding to user events that, but it is also the correct way to do concurrent programming.
CHUCK: Right so I guess my question is, so I trigger an event, then does that function that needs to be executed get thrown on a queue somewhere and it just says okay these well these have all have their events fired so I just work through them or does it just execute them one on a time and does that kind of block the thread?
AJ: So events that come from the user like if you are on a browser, what’s usually happening is that most of the time, your app is idle, it’s not doing anything at all. And as soon as you start moving the mouse, then the browser says, okay there is an event that has happened the user has moved the mouse. Does anyone care about a mouse move? If anybody cares, immediately invoke their callback. Most of the time people are not listening for mouse moves so nothing happens and so the browser continues to in idle in between every incremental mouse move. Eventually you’re going to click on something and then the browser says okay you click on something, is there anybody who are registered a listener for that thing, if so, run their code right away. So that is basically how the browser event system works.
Essentially a timer that elapsed is basically equivalent to the user moving their mouse clicking on something. Except that the browser is keeping track of how much time has elapsed.
CHUCK: Right. So the other question I guess that brings up is, let’s say that I am being really smart and I set things up so that on mouse move, I have like 10 different events that I’ll get triggered because I moused over a certain dev. So does it execute those in a specific order or does it just you know a trigger them all and spin off threads for each one or how does that work?
But what happens, historically, there’s not been a case that it was standardized. But now the rule is, because it’s like essentially works its way everywhere, is they are executed in the order that they were registered. And that’s also what is true about jQuery events because for a long time.
So basically, you mouse over and the browser says okay, event has happened, does anyone have any callback? And there is a list basically, internal, which is the list of the callbacks. It would basically just run through them in order until it is done running all those calling in order. It doesn’t go back and say, okay we are now idle.
What’s actually really important is that, the only time that the browser is willing to render things, is during the idle state. Basically, you can easily make the browser hang by simply saying when you click on this, do a loop and wait a minute, wait a second. The browser, basically AJAX, no other callback can run.
The browser is sitting there saying, okay I’m running code and it’s not like in the back of the browser, it’s always like oh, AJAX will come back running that. The browser only does those things when it’s idle. So basically it’s in the middle of running those callbacks.
CHUCK: Okay, and that’s the advantage too, is that it runs stuff when it’s ready and you can just say okay and when this next thing is ready, then run so we can go back into that idle state and do its other work?
JAMISON: So related to do this stuff, is there some kind of way to the see the contents of the event queue in the browser? Is there any kind of something like that?
AJ: So if you are using JQuery, there are ways to inspect jQuery’s internals which are soon going to be exposed to get it. Then there are also discussions that the browser exposing the callbacks and so John Resig of jQuery occasionally asks like, what can we do, to improve the browser for JQuery? One of the things on his list is always like; give me access to those for callbacks. That way if we have that, it will be easier for us to use that system instead of doing our own.
Basically, if you use jQuery, under the events, sorry the new data cache and you can go and inspect that and there is an events property in there. However that is ultra-ultra private it is perhaps used for debugging not for actual code. But that does have the list of all the events and all the callbacks.
CHUCK: Alright. Has anyone has something to ask or add?
JAMISON: I was going to say I have seen people do, what Yehuda was saying, where they create a loop and check the time and just do that in the loop, because they don’t understand the setTimeout or they try it to make it synchronous. I’ve seen that, where they will force it to wait a second synchronously and that’s just a terrible idea.
JAMISON: So a really common case where this is done on purpose is, the ad companies, they would like to be notified when you leave the page. They do not want to have to follow the normal rules. So what they do is, they register onUnload hook, but on onUnload hook will run and basically the browser doesn’t say when you’re done, will just sit there waiting any callback it’s like immediately shuts you off.
So, ad manager, actually, I would really like to know, when you left. So I’m going to make an AJAX request or whatever it is that I would do, and them and I’m going to sit on this spin loop forever waiting for like “n” amount of time like 10 seconds or 5 seconds, until I allow for onUnload hook to finish.
Basically what that means is sometimes you may notice you close a tab, you’re like why is this tab not closing? Why is it taking several seconds? It’s because probably, there is an onUnload hook registered on that page that is intentionally blocking the browser from closing, so it can force the AJAX request to complete.
Yeah I think I’ve heard, and am not sure if Chrome has done this, but I think that Chrome is going to not allow this to happen. Like it is going to force close onUnload hooks, but obviously that has implications for ads and blah, blah, blah.
JAMISON: I’ve never thought of that before I had that problem where we wanted to delay it.
CHUCK: So your example when you’re using setTimeout and then it checks the time and things like that, you’re talking like there is a better way to do that?
JAMISON: Well I think what AJ was saying is that instead of using setTimeout people are like, they just do a loop and then inside the loop they do like, the var date = new date and inside that loop they are like, if newdate – date is bigger than a 1000, break. I would like to wait 1000 milliseconds now and so they do that. What you should do is you should use setTimeout.
YEHUDA: That is different from what I was saying before earlier on.
CHUCK: That makes sense all right. While we’re still kind of getting to the flow on this podcast we are going to go ahead and get into the picks. I used to explain, like every time, on Ruby Rogues what they are.
If you’re not familiar with the format of this podcast, basically a pick is something that we enjoyed that we used, that we liked it doesn’t have to be code related and it’s just you know it’s just kind of a chance to share what we are up to and things like that.
So you know sometimes people will pick things that they are working on right now. Sometimes people will pick something like TV shows and stuff that they are listening to.
Well will do the picks and we’ll start with AJ.
AJ: Why don’t we start with you so I get the format of this better?
CHUCK: Okay. We will start with chuck.
One other pick that I have, and that is something that my wife and I have gotten into, we have a Netflix subscription and we can watch the Netflix movies through our Blu-Ray player through the wireless and we’ve really been enjoying Merlin the adventures of Merlin and it’s a BB- BBC show (man and cannot talk today.)
It’s a BBC show and basically, if you like the canonical Arthurian Legend then this show probably isn’t for you, because they have changed a lot. But it’s a fun show to watch and it’s really, it takes some interesting turn here and there. So those are my picks and anyway Yehuda, why don’t you go ahead and be next since you are now a veteran of the picks because you were in Ruby Rogues this morning.
YEHUDA: Yeah I feel weird I cannot think of anything obvious that I didn’t know what to say. I’ll just repeat what I said this morning. Okay. So a couple of books.
So I recently started a company called Tilde and I’ve sort of been thinking about a bunch of entrepreneurial topics for a while and sort of anticipation and joining a company. And two books that I really recommend if you are either starting the company now or thinking about starting a company or if you are in a company where you have full control over certain product design and all shipping and all that. Would be link start-up book which I think is like sort of-
CHUCK: Cut out there for a second Yehuda.
JAMISON: I just Googled “Tilde” and the first thing I found was this enormous picture of Arnold Schwarzenegger. I do know if it’s related to Yehuda company or not. But probably it is.
CHUCK: Yeah, it looks like he dropped off again. Peter, why don’t you give us some picks and when Yehuda comes back we will let him finish.
PETER: Okay cool just so you are aware Charles, BBC have also done a thing called Sherlock which is bringing reading Sherlock Holmes out to modern day which is really, really cool as well so. Just watch out for that for anyone who is on BBC at the moment.
AJ: It’s pretty good.
CHUCK: I heard it’s good.
PETER: It’s pretty good. Which I didn’t wanna watch it at first but I looked right into it so yeah, good stuff.
CHUCK: Alright. AJ.
AJ: Okay so since this is our first episode, I feel like mandatory to mention the Crockford Videos and YUI Blog. I take a lot of my coding style from Crockford recommendation and to have just learned a ton by watching those videos and re-watching some of them, because it was way over my head the first time I ever came across them. So I have a link for that.
And also I just found a really cool Node module that lets you send SMS text messages through Google Voice. That is pertinent because we are testing some software. We wanna make sure that our devices are up continually and that there are no crashes or stops in service. And so I’m thinking to use this along with our tests to have it send me a text message anytime something goes down.
So I’m reeling to that. It’s called Node Google voice.
CHUCK: All right sounds really cool. I may have to look into that. Jamison.
JAMISON: My first one is definitely 750words.com. So it’s 750words.com. It’s like it’s my secret diary thing. It’s kind of based on the idea that you should do your morning pages like write some every time you get up in the morning to kind of get your brain flowing. I have been doing it for a couple of weeks and it’s actually made a difference. Lots of times it’s full of like, Oh! so early I’m so tired when I write but I found that it helps me kind of reflect back my life and also just have creative time built into think about stuff. So that’s a great one.
And then my other one is (it’s kind of an old one) but there’s a book called Working Effectively with Legacy Code. It’s a big old nerdy programming book, but it’s basically how to work with code that isn’t under test and how to break it up so that it is testable so you can maintain it and change it without fear of breaking stuff.
So those are my picks.
CHUCK: Alright sounds good. Really quickly, just a few business items.
I am hoping to get this into iTunes pretty quickly and so if you could give us a review that will be great. I also mentioned that you know if you’re used to some of the other podcast that I do, they kind of have their own flow and we are kind of new to talking to each other, so, give us a few weeks to kind of gel and then thing I think these are really going to take off. I know that there were some continuity issues before.
So other than that, go check out Fluent Conf for Peter. It sounds really interesting is that going to be in San Francisco?
PETER: Yes San Francisco, May 29 through the 31st.
JAMISON: I think its .org oh, its .com.
We will catch you next week!