 I'm Jim Menard and I'm going to be talking about Ruby in the clouds, specifically the adventures that I've had bringing Ruby and Rails and making them run on the 10-gen cloud computing platform. So first of all, who the heck am I? I'm an old fart programmer. I've been programming since about 1980 and using Ruby since about 2001 and Rails since the beginning. Let's see now. NQXML, the first pure Ruby MIDI parser, XML parser, and MIDIlib, a MIDI file parser, that's just kind of develops my street cred before we get going. Of course with a jacket on, I don't know if I have any street cred. I joined 10-gen, in August 10-gen is a startup in New York City that is developing a cloud computing platform. The founders saw that they were solving the same problems over and over again for every startup they went to. How do I deploy my applications? I have to worry about setting up systems, distributing them, getting them running, managing them. So we're building a system where you don't have to worry about any of that stuff. It's a kind of development and deployment platform. The most important reason I'm here today though, actually, is less to tell you about how I did things and more to pique your interest so that you go download all this stuff because it's all open source. And what I'd really, really like is your feedback so that what I'm doing in Ruby and Rails and some of the compromises I'm making that I'll be talking about feel Ruby-ish and are Ruby-ish because I've had enough experience with other languages that I'm not always the pure Rubyist, the best Rubyist that I can be. So how many of you have had experience running software in a cloud? First of all, running your apps in the cloud. Okay. How many of you have heard more than one definition of the word cloud? Oh, yeah. So here's our definition. First of all, distributed deployment. There's more than one app server. There's more than one database server. They're in physically disparate locations and they talk to each other and you don't have to know about how or where they are. Second, it's scalable. Scalable in the sense that ZShaw defined a while ago in that resources are expandable at any time. If you need more CPU, more storage, more bandwidth, the system will magically take care of giving you more, whether you're running on more servers or not. You don't care. And finally, we're developing what we call platform as a service where the entire platform is available to you if you wish as a service on which you can deploy your apps. Or you can take our software and run it yourself. But the idea is that this whole platform is management free. You don't worry about the operating system and the machines and all that kind of thing. If you're running it, for example, in our cloud. This isn't a commercial for 10Gen, but since I'm developing for this particular platform, I kind of have to set the base of what this whole platform is about. The key takeaway point is that this cloud system is in many ways similar to other cloud systems. It's not terribly unique except for a couple of specific things. So on the left, we have a typical lamp stack where at the bottom level, of course, you have the operating system, usually but not always Linux. On top of that, a database like MySQL, sometimes an object relational mapping layer. On top of that, MemcashD, which just stands for something that helps with performance that your application doesn't have to worry about. And on top of that sits a web server, such as Apache or Lighty or something like that. And finally, your application sits on top. And it is written in either Ruby or Python or PHP or some other language. Well, in the 10Gen world, as in other cloud platforms, things are a little bit different. First of all, yes, there's an operating system under the covers, but you don't care or know what it is because you're not managing it. The second thing is that we have a database we've called Mongo. It's, I want to say it's an object oriented database. Technically it's not, I'll get into that a little bit later. But basically it's a distributed grid aware database that's non-relational. On top of that sits GridFS, a file storage system. It's not a file system. I'll be talking about that later. On top of that sits the app server we call Babel. And we call it Babel because it can run multiple languages. JavaScript, Python, Ruby, PHP, more coming in the future. And the cool thing about that that I'll get into later is that each language can talk to the other languages and run code in the other languages in your application. So conceptually the 10Gen platform is much more similar to Google App Engine than anything else. And this whole thing can run on our servers or your servers or an Amazon EC2 instance for example. So I've already talked about these pieces. The platform consists of the app server, the database, some libraries and modules I'm not going to get into a lot of detail. They are available to you to use. They happen to be written in JavaScript. JavaScript was our first server side language. But that doesn't matter because your app can just use it if you want to. As I mentioned, it's available now, it's in alpha. We have two real customers, but it really is in alpha. It's open source, you can go grab all of the source. Mongo is written in C++, Babel is written in Java. So you can compile them all. There are some dependencies, so it might be easier to download the SDK, which just prepundles, prepackages some stuff for you. And you can, if you want, run your app on our servers, in our cloud. So Babel itself, as I said, is written in Java. It supports a variety of languages. I've already talked about the libraries. It is server interface agnostic. We were trying to come up with a good phrase for this. There isn't a good phrase. But different web applications and different technologies require different ways to speak to the app server. For example, CGI is one of those ways. WSGI for Python, RAC is another way in the Ruby world that you can plug your application into different app servers. So we're server interface agnostic, and I'll show how you tell us which your app is going to use. And of course, with Rails, you'd use CGI. So we have some frameworks already running on Babel, specifically Rails, Google App Engine, and Django, already run on our platform. The Rails support is pure Ruby. So there's nothing in the app server that knows it's running a Rails app. A big caveat, various values of running. They're not all running all the way. They're not all running well. Active record support is not there for Rails yet. I have pre-pre-pre-alpha stuff to show you. But the point here is that what we want to do is let you take your Rails app, or Django or Google App Engine app, just deploy it on the cloud, and not have to change anything, which also means you can take it away and not have to change anything. So there's no lock in here. So down below, the app server is gridFS. As I mentioned, it's not a file system, but it is file storage. The files are stored in the database. And since the database is aware of the cloud and available to all of the instances of your app running all over the cloud, so are these files. The cool thing about these files is that you can attach metadata to them. So every single file, kind of its own metadata that you can attach in Ruby code, and I'll show you an example of that later. And it will be available next time you load the file. So the database, Mongo, as I mentioned, it's not relational. It's a document database. Couple of, I should bring buzzword bingo cards or something like that. I'm trying to avoid buzzwords, but it sometimes can't help it. What we mean by collection-oriented storage is you don't have tables like you do in a relational database, where each table stores a certain kind of thing. Instead, each collection in Mongo stores trees of objects. So your student object, which contains an address, which contains and references other courses that the student is taking, that's all stored in the database as one thing. I lied it's not stored as an object, it's stored as a binary representation of JSON, basically. So it takes that hash-like complex structure and stores that in the database. The app server level is responsible for translating that into objects, and then my level is concerned with turning those into Ruby objects. You can, when you run a query, you can query using sub-objects, so you can say, for example, student, like I said, the student contains an address. You could say in your query, student.address.city equals Orlando, and it will return all of those students. Two points here, though, that aren't up on the slide. One is, you don't have to use Mongo with Babble. You don't have to use Babble with Mongo. So you can use them separately. If you deploy this yourself, you can use the Babble app server and use MySQL instead. You can just take your Rails app and start using MySQL with it right away. And the other is that, again, this isn't specific... Having to think about bringing Ruby and Rails and things to this platform isn't specific to Mongo because any application that's going to run on a cloud that has a non-relational database has to think of all of these same issues. And so one thing I'm trying to do here is to learn how the other systems solve these problems and deal with the mismatch between object relational mapping and pure object storage. I'm gonna whip through these features because they're not key to this presentation. Mongo has the basics, create, up, late, and delete, indexing, sorting, limit, offset, regular expression searches, full text search. You can run code on the database server. I'm gonna talk about that a little while later. But the idea is that the code is in any language. So you can send Ruby code over and run the Ruby code on the database server. The idea, of course, being if your query has to perform complex calculations, you want those calculations to run on the database server so you don't have to send data back just to see if the record matches your query. Of course it does replicate, Mongo does replication because it has to be to live on the cloud, coming soon, locking and sharding. They just a little bit, we're getting to those right now. So what languages do we support now? JavaScript, PHP, Python, Ruby, more under consideration. For example, we're considering exposing Java because Java is the language the whole, the app server's run on. The point again I wanna make here is that any of the code running in any of these languages can call and use code running in any of the other languages, which makes my job a little tricky, but fun. So to run Ruby on Babble, we use JRuby114. I just took a look at 115, which came out a couple of days ago and there are some changes in the Java interfaces to the Ruby classes. So it's gonna take me a little while to get that going, but that will come soon. Right now we're running Ruby 186, whatever version of 18 that JRuby runs. I have an internal flag for running Ruby 1.9 through JRuby, have not yet exposed that publicly, but I'm looking to do that and I'm trying to look of A, the cleanest way to do that. I don't think I can auto detect it. So you're gonna have to tell me you're running 18 or 19 and I wanna make that as painless as possible. And I had to be, and I don't remember offhand what it was. But as I mentioned, in this world, JavaScript is the lingua franca. It's kind of the first among equals. So a lot of the issues I've had to deal with have been, of course JRuby does a beautiful job of translating Ruby objects to Java objects and back and letting them talk to each other very nicely. Well, I can't use any of that because the exchange between, the exchange between code when you're calling other code is done using the JavaScript object model and JavaScript functions. So we have wrappers for that. I'll be talking about all this more in a couple of slides. The other thing you have to consider when you're running in any environment actually is what scope are you running in? In other words, what information do I need about the environment? And in a platform where you can have multiple languages running, when one language calls another, it may have information to pass and that gets passed in through the scope and likewise information can pass back up. So our scope contains a lot of stuff but the basics it contains the object representing the database, the object representing the application context, the server context including the request and the response. Some globally available classes, they're JavaScript classes but in Ruby you can treat them just like Ruby classes and instantiate them and subclass and all of that. There are some top level functions that are available and these things we call file libraries which are essentially load paths. We have three magic load paths that I'll talk about later. So the functions that are in the scope, the top level functions I put into a top level module called xgen and that gets included in objects just like kernel does. So all of those top level objects that were defined in the app server are available to all of your objects if you wish to use them. Likewise the objects that are in the scope, well first of all the scope itself becomes a global object called dollar scope and all of the objects in the scope become global objects too. This is one decision that I've made that I'd like to hear more feedback about. Does that make sense? It doesn't sound really stupid. So I'd love to get your feedback on how that feels when you start playing with it or do our global's so darn evil that there's a better way to do this or a more Ruby like way to do this. Aside from the database instance, your user code probably won't be using many of these global objects anyway. Some of the glue code does. All of the glue code again is written in Ruby and it will use things like sometimes the request object or the response object to set up input and output. When you modify one of these globals it goes back into the scope and likewise when you create new global globals they go back into the scope and they're available for other code in other languages. So how do you call other code? Well by using require or load. It looks just like any other Ruby file call. So what I've done is overridden require and load so that the first thing it does is call the regular require and load. So normal behavior doesn't change at all. There's no change. But if that fails, then the next thing it does is try again using the internal loader which knows about other languages. And these three things, local core and external are the three file libraries or essentially additions to the load path. If you prefix the file path with load slash or core slash or external slash I'll look in those three magic places. So far I've done that instead of adding those three to the load path that's an internal discussion we have around security for example. Because since you're running on a server that may be running other applications we are going to have to limit your exposure to the file system and that will include limiting what you can do with the load path. That Xgen module I talked about also holds on to some other things. There's a sub module called Mongo that holds on to database related classes. These are Ruby classes that are wrappers around the JavaScript classes for the object ID object. I just said the object ID object. For cursor base and for doing logging all logging is done to the database. And the Xgen Rails module has only one thing in it right now although there's lots of other Rails stuff that contains the implementation of the session storage adapter because as you may know in Rails you can decide whether sessions are stored on disk or in the database or one or two other ways. Well there's one more way here storing it into the distributed database. And again that makes perfect sense because now when your sessions live in a distributed database then no matter where the request comes in you don't care about load balancing you don't care about any of that because the session object is always available to all of the instances of your application. I've exposed the grid FS file store through a class I've called grid file which feels a lot like a Ruby file. So very simply when you require its class you can open it for writing, open it for reading, open it for appending and under the covers right now it uses string IO and slurps the contents of the file into a string. I know that's a very very bad thing to do but right now the Java implementation underneath doesn't know how to append stuff you have to go through jump through hoops so once I fix that in the app server this will go away and this will not slurp the data into memory until you need it which is of course what you want to do. The thing I'm not showing here is that grid files can have attributes. So again here's where I want to open it up to the community what should this look like? What I did right now is you could say and treat F like a hash and say F bracket foo equals 42 and now you've just set the attribute foo to the value 42 and the next time you read it you could read F bracket foo and get to it. What I bumped my head into was if F looks like a hash but it also looks like a file what does the each method return? What does it iterate over? Does it iterate over lines in the content? Does it iterate over characters or does it iterate over these attributes, the key values? So again right now I'm leaning towards hiding the attributes not hiding them excuse me putting them in a sub object so you'd say F dot attribute and then access them that way but again opinions on how that should look and what feels most Ruby like would be greatly appreciated. Logging I said happens to the database using a capped collection a capped collection is simply a database collection in which you specify a maximum size a maximum byte size and optionally a maximum number of records and so old records get purged as new ones come in. How do you use it? Well if you look in the Ruby logger code you'll see that it uses this thing called a log device I just made one of them that knows how to write to the database it was really as simple as that and again it's pure Ruby and it uses that dollar DB object and that's all it uses it's even slightly magical. We have a command line shell that it's not too surprising if when it fires up by default it fires in fires up using a JavaScript but if you say shell minus minus Ruby it will use IRB it's really IRB it's really sitting there and there's just a little bit of code that hooks it up to the app server. So the biggest challenge I've had so far as I mentioned is in reconciling different object models when getting Ruby to run in the cloud. A JavaScript... How many people are familiar with JavaScript enough to know about its inheritance model and how you access instance variables? Okay a couple of you. I'm going to greatly simplify and get it wrong by saying a JavaScript object feels an awful lot like a hash with some magical syntax and a different object inheritance model. You don't inherit through using classes in JavaScript you inherit through using prototyping which means you don't say it's not that my class is this class is that I'm like that guy over there except I do these things differently. So a very different object model. So I mentioned I have to use these wrappers a JavaScript object when it comes into Ruby becomes a class called JS object which subclasses hash. It's sort of like a hash plus plus if you will. If you look at the top section here this would be legal in both JavaScript and in Ruby in Babel. The first line is pure and simple. The object has keys and values and so you access a key just like you do a hash in Ruby. The second is magic I do in Ruby which is essentially an accessor method but in JavaScript those two things are exactly the same. I expose them the same way in Ruby but you don't have to worry about that. Just like a hash if you wish. Until you get to functions because this object can have functions hanging off of them of course and you just write you call just like you would any other function the JS object dot woogie and you pass in your argument and that call calls a JavaScript function and bundles your arguments up into JavaScript objects as they go in and calls it as JavaScript code. JavaScript array objects become JS array which is again a subclass of Ruby array with a few extra features because JS JavaScript objects are a little more complex. A JavaScript constructor function becomes a class in Ruby so that you really can instantiate those objects and subclass them and do all that kind of nice stuff. Likewise a Ruby class which you can pass in to certain library methods we have becomes a constructor function. So when you call the constructor function JavaScript land you start getting a wrapped Ruby object. Finally I mentioned functions in the scope turn into plain old functions or methods in the Xgen module but if you have to take a Ruby block and give it to JavaScript as a JavaScript function you can do that too. An example down here this last line if you can see it the first thing is the database object the second thing dot X is just a collection that's a JavaScript object too. Dot find that's a JavaScript function called on the JavaScript method and that will return all of the objects in that collection except it doesn't it returns a cursor object. The cursor object has an each method because JavaScript is like iterating just like us Rubyists do but I need to pass to it a JavaScript function what I can do in my Ruby code is pass in a block and the block gets bundled right up turned into a JavaScript object everything up to the first curly brace is pure JavaScript and I pass the block in it turns into a function and it gets called with no problem. So I mentioned before wouldn't it be nice if I could just use jRuby's built-in native Ruby to Java and Java to Ruby in fact I had a good chunk of this stuff running early everything was pure Ruby with no wrappers whatsoever until I came to a particular problem. Our JavaScript is written in Java we're not using jRino yet and I found that the database collection object the one that has the find method has a JavaScript function called find and a Java function called find and the way jRuby is written if you wrap a Java object it will always insist upon using the Java function and you have no way of overriding that you have no way of putting a hook into that it's declared private static final only on Thursdays if you have the secret password you'd really have to hack into jRuby very deeply to change that behavior so that led me to having to write these wrappers but the wrappers themselves are fairly lightweight and I go to great troubles to make sure that they're cached so once you wrap something in either direction it's only used once for that runtime another instance running in another runtime will get another wrapper the connection to the app server you have to declare that because Babel doesn't know whether you want to use CGI or RAC or anything else so that's a one line configuration script one line in a little configuration file I put threading up here just as a token resource to show that in any application environment where you're running more than one application especially more than one application by different people in different languages you have to lock down resources to a certain extent we can't let you create a bazillion threads because it'll take over the machine we can't let you fill up the file system or anything like that so we're starting to look at sandboxing and how that will affect applications it won't affect how you write your code it might affect what you're able to do so in pure Ruby there are basically three ways right now to get to this distributed database with native queries and that is JavaScript objects in Ruby land and you notice the arguments are hashes which are turned into JSON on the server side and notice that we're searching by name using a regular expression that turns into a JavaScript regular expression secondly I've come up with a class called XGenMangoBase which is really really similar to ActiveRecordBase as far as it can be we're going to talk about that a little bit more in a couple of slides here's a simple example and hopefully it looks really familiar because you could drop that into an ActiveRecord app and it would run exactly the same finally I'm working on getting ActiveRecord running there are a couple of challenges there not the least of which is that ActiveRecord assumes that it's using SQL and running with a relational database it's fairly insistent upon that so all I have it running now doing some very simple things if we have time I'll show you later but something I forgot to mention earlier or I glossed over is that Mongo is schema free each collection doesn't know or care what's stored in it there is no schema so when you insert something into a collection it'll take the fields and just store them the next thing may have the same set of fields and it may not and Mongo doesn't care ActiveRecord cares very much so what I do is lazily the first time it's needed I read the db-slash-schema.rb file which is a Ruby description of your schema and so it'll set up all so it lets the code know about your tables and know about the columns and their types and everything like that and sets up indexes too so if you've defined indexes they'll be in there and the Mongo database will have its indexes set up as well I just threw up Object ID here because not Mongo but the app server requires that the primary key of every object be one of these things but in Rubyland I've done as much as possible to make sure you just treat it as a string so it's essentially a string key called underscore ID I pointed out earlier you can use Mongo without Babel and vice versa and so we're looking to get pure Ruby native driver for Mongo we haven't had the time to do that yet if anybody's interested we'd love to talk to you about that come see me after and we'll give you as much information as you need or you can just go download the source and start hacking away two seconds on Xgen Mongo base its API is very similar to ActiveRecord base there's one additional feature that I mentioned earlier that Mongo knows how to run your code on the database server the problem is getting the code there it needs the source code and the bad news is in JRubyland once Ruby is compiled you can't get to the source code so there are three options as I see it right now and I'm really open to discussing this and getting feedback first of all we're considering internally a SQL like language and we've experimented with it already the source code is out there second of all I'm looking at hacking JRuby but I don't have that much JRuby foo yet and getting into the AST and the parser and all that is going to take me a while to do and to find out if it's even possible third as a really horrible compromise you can send over a string that contains the function definition I will see an example of that later it works it's not elegant and it's not nice we know that let's take a very brief look at some sample code and here's where I so the first thing up top is an Xgen Mongo base class and it looks awfully similar to an active record class except for the first two things instead of a table name I say you say collection name and you have to tell it remember this isn't the code that looks at DBE schema because we're not talking about Rails right now you have to tell me what fields it's going to be and then it's going to be an Xgen Mongo base the nice thing you notice created at and updated at are there well the magic that happens in Rails also happens in Xgen Mongo base those fields get updated for you automatically without you having to worry about them other than that this class has one address and has many scores so that's an array of objects when you save this student the entire tree of objects it is the exact same as any other active record controller there's nothing to see here these examples come right from the R doc for the find method in Xgen Mongo base so I'm not going to go over them in detail except to say that they should look awfully really familiar they can't do everything active record does but it can do an awful lot this example right here the horrible horrible hack of passing a javascript function in as text to the database server I'm not proud of it but there it is okay so how do you run Ruby again forget about Rails how do you run Ruby on Babel well it only needs to know a couple of things Ruby needs to know about standard in and standard out and Babel needs to know where to send those things and I'm sorry what's the other thing my mind blanked we also support erb natively so if you point the app server to a foo.erb it will just run as erb to set this up you have to have one magic file that contains I didn't show this magic file contains a function defined in Ruby that is essentially a mini router I showed a really simple example that's formatted very badly to just let it fit on the screen but this function which gets shoved into a global object so the app server can see it gets two arguments the URI and the request so you can look at the URI, match it with regular expressions and send it on to whichever of your Ruby files you want so the nice thing about getting Rails running is that if Ruby is already running there's not much to it Rails has to know about its environment I get that from the name of the server you're running on basically and if you're running in development it just assumes its development database we've talked about it has to know Babel has to know about that Rails wants CGI and where to store the sessions we already talked about that it would be nice if Rails didn't have to worry about serving public files just like it doesn't now in most cases so the magic init file I'm going to show you sets up a sort of meta routing where it looks at the URL first the URL if that file is found in the public directory it serves that directly without having to go to Rails logging goes to the database and we set up the default Rails logger for you so you can just use logging normally as you would in Rails and it works and finally a user in Brazil is working on a generator for generating Xgen Mongo base objects how do you get your Rails app onto Babel it's really simple first you freeze Rails we don't ship Rails we don't want to tie you to any particular version so you just freeze it second you add two tiny tiny files we're going to see in a second and third you have to figure out how you're going to talk to the database either use Xgen Mongo base active record which isn't ready yet or if you're not running in our cloud you can use MySQL or any other persistence mechanism and it just doesn't matter so here are the two small files at the top level of your application you need a magic file underscore init that could be .rb.js.py for python it doesn't matter but in Rails land you just need that one magic init file which does a couple of things it tells Babel to use CGI and it sets up that meta routing I talked about which serves public files directly and finally the next thing it does is it says send all requests to public Xgen dispatch which is a new file and that includes a file which does a little bit more it sets the Rails end creates the default logger of record and the Xgen Mongo stuff then it runs the normal Rails configuration so everything you've got in your existing Rails config just works creates a new session storage adaptor excuse me and then calls the regular dispatcher and now you're in pure Rails land I've got time to show you these apps running if you're interested both a Xgen Mongo base version and an active record version I might as well fire that up and show you because it'll also show you how to start things so here's the live demo part that could come crashing down on my head we'll see I am using the the raw source version rather than the SDK in the SDK it's a one line start up instead of a two line start up so first thing I do is wow it's a little tough to type this way start Mongo the database is now running next I start up the app server and point it to the root directory of my application and it rebuilds because I'm running the development version it rebuilds everything and then starts running and now it's listening I come over here localhost 8080 and I'm going to let you see this for a second A to show you that when it's starting up it's painful right now we want to speed this up but B to point out that just like with Rails if you change one of your files you don't have to restart everything so I don't want to scare you by the fact that it's taking so long to start up that's a one time thing so here's my Ruby on Rails on Babel application it uses two different database collections a collection of courses and a collection of students each student has an address and the scores or the grades that they've had in each class so where's my mouse here's the part where I panic here we go so this is pure simple dumb little Rails app that has nothing exciting about it except the models are different right now in this version what we're seeing here if I go to the students I'm showing the name email address the scores so let's add a score to Bender and we'll say that he took buggy quick repair and only got a 2.0 in the course now if we look at the controller what we'll see just happened is the code retrieved that course object from the database and shoved it inside the student so it is now inside an array in the student so you might think now we have two of the same object in two different places well the app server and Mongo are clever enough to do what is essentially a foreign key when you start saving an object it looks at all the IDs and it says oh wait I know about that object I know what collection it is stored in and so I save a DB ref we call it is essentially a foreign key so you deal with objects we worry about the foreign keys not you I whipped up a little page that shows the logs that are stored in the database so these are the logs that are stored there and I also whipped up a little page that shows that sessions actually work it's not very exciting but if I were to open up two browsers you'd see the number increment every time I refresh the page here and every time I refresh it somewhere else and if we were running on multiple machines it would all work magically and happily so tada that's done but now what I'd like to do is show you an active record app and here's where I really cross my fingers and wave my hands a lot because there's a lot of stuff that doesn't work yet so I took the code from the pragmatic programmers application development in Rails and downloaded it from their site and unpackaged it and didn't change a thing so the Rails app itself has not changed it is pure active record it's everything that came out of the book and once again I do a song and dance while things load so what you'll see is the main store come up and it's going to show some products that were retrieved from the database it essentially did a find all I loaded the data into the database by taking the migration one of the migrations they have loads test data so I just took that and extracted it and just ran it from our shell and did nothing else so that really is using active record to really retrieve the data here's where I wave my hands and I don't think it's going to work correctly I set up the 10 gen user just like they did and it didn't work and I've got a bug that I introduced a couple of days ago so wave my hands that would have taken you actually to the URL admin and here's where we have a glaring hole in our architecture we right now reserve a couple of URLs and that's really really horrible and evil and we know it and we're going to change it and I apologize for it right now this is the admin interface for your app running in the cloud or on your machine so you can actually look in the database here's the products collection and we can look at it and see what's inside of it delete records and search you can look at the raw logs do some profiling and stuff like that I'm not going to get into any of that right now I want to wrap up by saying first of all thank you very much for coming I really appreciate it I hope that I haven't put you to sleep and you've got at least a vague interest in downloading this and trying it go to www.tengen.com we also have mailing lists and blogs and all that kind of thing the code is available there it'll point to our github repository yes on their own machines you could run it with MySQL with no problem the higher stack you can run on your machines it's open source, grab it, run it and get it running absolutely and not have to worry about management and such yes I just started this active record work a couple of weeks ago and it's so weak and there's going to be a lot of thinking and planning and doing to get it running as close as I can to real active record yes so it's not ready yet from a business point of view how are you guys trying to compete with something like Google App Engine? from a business the question was repeat your question sir from a business perspective how are we going to compete with Google? I'm not a business guy so I don't have a ready packaged answer to that question but basically A, we've got more languages out of the box B, it's completely open source C, you can run it yourself so those are interesting enough differentiators that we hope you at least take a look and consider us billions of records in the MongoDB billions no billions yes it does some operations faster than others and we know where we have to make it better it's so it's much much faster than my sequel doing certain kinds of things but not others and I don't know what they are, I don't have that information with me not yet, locking is coming yep and we don't know at what level that will be yet record level, collection level, I would hope it would be record level that's what we're planning is record level locking yes is it possible that Tengen could be used to make a sort of Tengen at home type application where the clients are distributed from raw to interleaved the question is, could Tengen be used to create a SETI at home type application where many many many different clients are running a distributed application excuse me I'm going to say no because the hard they'd all have to be running good question I'm not sure I haven't thought about how that would be architected right now it's intended to be used as kind of part of a server farm when the clients become part of that server farm now the infrastructure has to know where all of those clients are at all times and I believe that part of our infrastructure assumes that everything knows where everything else is at all times so I don't think it's ready for clients to be dropping in and out I'm not sure it's ready for that kind of application but that's something I'm going to take back to the people at Tengen and ask if they've thought about that kind of application thank you any other questions yes you're introducing middleware in that layer so you're obviously losing some performance but the horizontal scalability so what does that trade up the question was about performance since these languages can talk to each other and there are wrappers involved that degrades performance but on the other hand this whole thing is designed to be scalable horizontally so more servers get added magically for you when you need them and how does that affect what's the overall performance gain or lose boy that's a good question we're early enough that we know we want the scalability to matter much much more than the wrapping and we know we can do it and we've got bright enough people to do it and we're already working on that but I don't have any hard numbers for you yet so I have to wave my hands, I'm sorry what do you anticipate to be the biggest bottleneck what do I anticipate to be the biggest bottleneck would it be the database or the app server what would that component be is it going to be the database or the app server the app server and database connect over a raw socket so that's not going to be a big bottleneck and they scale independently so that is not a big bottleneck either I think it might be the context switching so we're going to have to worry about that most first we want to get it running right and then get it to perform we're at the late stages of getting it running right so we're not yet at performance but we've got enough bright people that that's why I'm there because I want to learn from them yes I'm curious to know why JavaScript was chosen as the lingua franca the reason we came on our website is because application developers are using JavaScript on the client why not let them use the same language on the server it's partly because one of the founders did this really cool implementation of JavaScript that's really fast and it was first it may not be the lingua franca forever the founder and the head of technology are still talking about that and they have differences of opinion and we're still very early stage and we're working on that it may not be the lingua franca for very long and so that may take away some of the wrapping issues because we were having internal tech discussions and among other things I was saying look if I didn't have to translate to JavaScript and I could just use pure JRuby I could throw away 80% of the code I've written and it would be faster but the other thing he said same here I'm using jython I have to spend a lot of time worrying about those wrappers all that would go away so there is interest in getting rid of that and getting rid of the context switch problems and would be more performant let me just check the time my time is officially out so I would like to thank you very much for your patience and kindness thank you