heroku[web.1]: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
heroku[web.1]: Stopping process with SIGKILL
heroku[web.1]: Process exited with status 137
heroku[web.1]: State changed from starting to crashed
After tons of boot timeouts of a Heroku Ruby on Rails app (Error R10), it was time to optimize the app.
What I did:
Removed some gems require on load and required on demand in runtime
watched the app’s log and analyzed the slowest gems.
Made sure no external resource access is made during boot (Redis, Neo4j, Solr) except MySQL which is on RDS and Rails requires this connection on start.
To do that, I pointed all resources to non-existing ones and started the app locally.
No operation is done with the DB on boot.
Removed rails_admin from the main app as it adds a few seconds to boot even if initialization is skipped. I’m going to create another, smaller app that’ll contain only rails_admin, its dependencies, models, observers etc.
Result: Heroku boot time less than 30s.
On my local machine I get 15s on production env (including the connection to external DB on RDS), but maybe it’s only because I have a faster CPU than Heroku’s (i7 2.7).
Jastor is an Objective-C base class that is initialized with a dictionary (probably from your JSON response), and assigns dictionary values to all its (derived class?s) typed @properties.
It supports nested types, arrays, NSString, NSNumber, NSDate and more.
Jastor is NOT a JSON parser. For that, you have JSONKit, yajl and many others.
The name sounds like JSON to Objecter. Or something.
with Jastor, you can just inherit from Jastor class, and use initWithDictionary:
123456789101112131415161718
// Product.h@interfaceProduct : Jastor@property(nonatomic,copy)NSString*name;@property(nonatomic,copy)NSNumber*amount;@end// Product.m@implementationProduct@synthesizename,amount;@end// Some other codeNSDictionary*dictionary=/* parse the JSON response to a dictionary */;Product*product=[[Productalloc]initWithDictionary:dictionary];// Logproduct.name// > Fooproduct.amount// > 13
Nested Objects
Jastor also converts nested objects to their destination type:
// JSON{"name":"1","children":[{"name":"1.1"},{"name":"1.2",children:[{"name":"1.2.1",children:[{"name":"1.2.1.1"},{"name":"1.2.1.2"},]},{"name":"1.2.2"},]},{"name":"1.3"}]}// ProductCategory.h@interfaceProductCategory : Jastor@property(nonatomic,copy)NSString*name;@property(nonatomic,retain)NSArray*children;@end// ProductCategory.m@implementationProductCategory@synthesizename,children;+(Class)children_class{return[ProductCategoryclass];}@end// CodeNSDictionary*dictionary=/* parse the JSON response to a dictionary */;ProductCategory*category=[[ProductCategoryalloc]initWithDictionary:dictionary];// Logcategory.name// > 1category.children// >[category.childrencount]// > 3[category.childrenobjectAtIndex:1]// >[[category.categoriesobjectAtIndex:1]name]// > 1.2[[[category.childrenobjectAtIndex:1]children]objectAtIndex:0]// >[[[[category.childrenobjectAtIndex:1]children]objectAtIndex:0]name]// > 1.2.1.2
How does it work?
Runtime API. The class?s properties are read in runtime and assigns all values from dictionary to these properties with NSObject setValue:forKey:. For Dictionaries, Jastor instantiates a new class, based on the property type, and issues another initWithDictionary. Arrays are only a list of items such as strings (which are not converted) or dictionaries (which are treated the same as other dictionaries).
After complaining to our developers about using the old, <1.8’s => syntax in hashes, I was challenged by my ninja colleague Avi Tzurel to create a script that will convert all the old Ruby hash syntax to the new 1.9, beautiful colon notation.
The crazy negative lookbehinds ensures that nothing like
12345
begin# ...rescueNamespace::Exception=>exend
123
defsomethingreturn:x=>1,:y=>2end
will get replaced. Turns out that after return you can only use the old syntax, or have curly brackets. Also, unfortunately, negative lookbehinds can’t contain Regexp inside them. So the multiple negative lookbehinds are like a big ‘or’.
Our really big project, with hundreds of .rb files, Gogobot, converted and is working great. Still afraid to do the final git push though ;)
Updated to Ruby 1.9.2 with ArthurN’s amazing fork.
Update: Apr 13th, 2011
Updated API, external script support and fixes.
The problem:
In Ajax-based sites, there’s a constant dilemma: How to get objects rendered in templates? In server side (and output full HTML)? Client side (and mess with JSON objects and HTML strings/DOM generation)?
What should be the role division between server and client?
Common Approaches, Pros & Cons:
A few approaches to output a rendered template evaluated with an object are:
Approach #1: Regular ERB Partial
Evaluate a simple ERB partial with a local object, and server it as a string to the client, simply by
Query the server for a JSON article and evaluate the template with this object into a string, and place it inside a container, using a technique as mentioned:
12
varresults=document.getElementById("results");// some container on the pageresults.innerHTML=tmpl("article-template",article);// article is an object, probably a result of an AJAX JSON request
Pros
Fast - requires the server to send only the JSON object and the HTML is downloaded only once as a template
Cons
SEO and accessibility - HTML code isn’t in the source of the page but being rendered after load
Approach #3: Regular ERB Partial With Marked Spots for Data Place Holders
This approach tries to combine server side and client side but requires a lot of work. It contains a regular ERB template and place holder markers like class names on elements.
The template can be first evaluated on the server with a Ruby object and on the client side it can be evaluated with a different JS object (probably from a JSON request).
And then, from a JS function, doing something like:
12345678
// article is an object probably from a JSON requestcontainer.querySelector('.data-title').textContent=article.title;container.querySelector('.data-content').textContent=article.content;vartags=container.querySelector('.data-tags');tags.innerHTML="";article.tags.forEach(function(tag){tags.appendChild(document.createElement("li")).textContent=tag.name;});
Pros
One template for both client and server (not really, see Cons)
SEO and accessibility - HTML code is downloaded into the source
Cons
On the client side - Must mimic the Ruby functionality with JS when it comes to loops, conditions etc. However, text values are pretty easy to embed. This code should probably written manually for everything that is not a simple textual content.
Must maintain data place holder markers
So…
In these three approaches, the developer needs to choose according to the task and the project requirements, or worse, maintain two templates, ERB and EJS.
Each approach is written in a totally different way, and switching between the approaches means a lot of work.
Introducing: Isotope - Ruby Hybrid Template Engine for Client Side and Server Side
So why not combining all the pros of the approaches together?
The biggest constraints to be considered are:
Client side doesn’t understand Ruby
Ruby can’t be translated fully into JavaScript
And the most important one: Template should be maintained in one single file for both client and server uses
Isotope is from greek - “Equal Place”. An equal place of editing a template for both client and server (Thanks @yuvalraz for the name!).
Using jbarnette’s AWESOME Johnson gem, Ruby and JavaScript can interact together!
This code reads the source of the EJS file, uses Johnson and John Resig’s technique and serves a string as an output.
Configuration
External JS files can be included in order to have special functionality in the EJS templates, on both client and server.
To include files, create a config/isotope.yml file and fill this array, relatively to the app root:
# ArticlesControllerdefshow@article={:title=>"Hello!",:content=>"World!",:tags=>[{:name=>"tag 1"},{:name=>"tag 2"},{:name=>"tag 3"},{:name=>"tag 4"}]}# Or an ActiveRecord fetchrender:text=>isotope_render_partial('articles/article',:locals=>{:item=>@article})end
Or, with a view:
123456789101112131415161718
# ArticlesControllerdefshow@article={:title=>"Hello!",:content=>"World!",:tags=>[{:name=>"tag 1"},{:name=>"tag 2"},{:name=>"tag 3"},{:name=>"tag 4"}]}# Or an ActiveRecord fetchend# views/articles/show.html.erb<%= isotope_render_partial('articles/article', :locals =>{:item=>@article})%>
Backups are important. But usually they are made daily or even less often than this.
Quick tip I wish I had known a month ago when my MacBook froze and didn’t boot after a fruitful, productive day: backup all the code in realtime, all the time, with Dropbox.
Every CMD+S sends the file to Dropbox, and that means, that if something terrible happens to my computer (can’t boot, coffee accident, or it gets stolen), I know that all my code is backed up to the latest save.
That doesn’t even mean you should put your code directory inside the Dropbox’s one, you can Symlink it, excluding big files that don’t need to be backed up, or if you’re short on space.
A template I use for Rails projects w/ Git, excluding the tmp, log and other irrelevant folders:
I once built a nested message board (using ASP & VBScript, bah). In order to print all messages, nested, I created a recursive function that queries the DB for all messages of a certain parent, prints the messages and calls the same function itself with parent ID of the current message. That was a disaster to the server, as a single page could execute about 100 queries.
I decided to move the rendering logic to the client side, since SEO wasn’t such a big of a deal for this, and the load time was critical. So at first I queried the messages I wanted (I could do this in one query thanks to the DB structure), I pushed the data to JavaScript, as a flat, unordered array of objects, using JSON:
The first approach to print this, nested, is using a recursive function in JavaScript, that, on every call needs to find the child messages based on their parentId, and actually mimic the server behavior (loop on root messages, query child messages, print, recursively).
But a way cooler approach, is to utilize the DOM itself for nesting, and to utilize a hash table indexer to store and find messages based on their id.
After creating all elements for all messages, a hash table (associative array, or just a JavaScript “object”) can be used to store a node based on its id, so when we want to find it, we can just use nodesById[someNodeId]:
Then, the magic of having all elements nested happens when looping on all nodes. Each node has a parent_id except root nodes. We need to find the parent of current node in the nodesById object, by using nodesById[nodeParentId], and append the current node to its parent we found. Root nodes appended to a root container.
That way, we utilize the DOM for native nesting, without a recursion, and a simple single loop. The array doesn’t even have to be ordered, and no worries about requesting a node when its parent isn’t exist, as all of the elements are already created before.
“`js
var treeData=[
{“id”:1,”parentId”:null,”title”:”1”},
{“id”:2,”parentId”:1,”title”:”1.1”},
{“id”:3,”parentId”:null,”title”:”2”},
{“id”:4,”parentId”:1,”title”:”1.2”},
{“id”:5,”parentId”:1,”title”:”1.3”},
{“id”:6,”parentId”:4,”title”:”1.2.1”},
{“id”:7,”parentId”:4,”title”:”1.2.2”},
{“id”:8,”parentId”:4,”title”:”1.2.3”},
{“id”:9,”parentId”:null,”title”:”3”},
{“id”:10,”parentId”:9,”title”:”3.1”},
{“id”:11,”parentId”:10,”title”:”3.1.1”},
{“id”:12,”parentId”:11,”title”:”3.1.1.1”},
{“id”:13,”parentId”:11,”title”:”3.1.1.2”},
{“id”:14,”parentId”:11,”title”:”3.1.1.3”},
{“id”:15,”parentId”:13,”title”:”3.1.1.2.1”}
];
function NodeItem(data) {
this.data=data;
var container=document.createElement(“li”),
title=container.appendChild(document.createElement(“div”));
title.innerHTML=this.data.title;
this.element=container;
} NodeItem.prototype={
// lazy children element creation - not all nodes have children
getChildrenElement:function () {
return this._childElement = this._childElement || this.element.appendChild(document.createElement(“ul”));
}
};
// convert all nodes to NodeItem instance
var nodeCollection=treeData.map(function (node) { return new NodeItem(node); });
// for faster lookup, store all nodes by their id
var nodesById={};
for (var i=0;i
I’ve been using Mac OS X for a almost two years. I like it, I really do. But there are a lot of things that drive me crazy. At least in the native/default configuration:
You cannot rename/move/copy files in a save dialog. And you cannot open the enclosing folder to do so. You must open Finder yourself and look for that folder. This should be useful if you just want to replace a file but maintain the original in a different name.
On that same file dialog, you can’t paste a web URL (http), which means, that if you want to open a file from web you must first download the it and then open it manually.
You can’t delete a single file from trash. What happens if you just want to destroy evidence of something?
Sometimes (e.g. in Chrome), when I mark text, it forgets where I started to mark from and where I ended. If I change the mark using Shift+Arrow/Shift+Click elsewhere, it either enlarges the selection when I wanted to subtract, or vice-versa. It should always proceed from the place the last mark was stopped at.
When multiple windows of the same application are opened, a click on the dock icon brings them all to front. Same for cmd+tab menu. To me, it seems it happens because of poor window management. When I have a lot of Finder windows it’s very annoying. Partial solutions: HyperDock (for dock) and Witch (for alt+tab between all windows, not apps)
You can’t cut & paste files. As time goes by I see how I really need it. Imagine you wouldn’t be able to cut & paste text, but only copy-paste-delete. Solution: TotalFinder
You can’t merge folders. Drag / copy&paste of a folder named A, onto a folder which contains another folder named A, will totally remove the second A and replace it by the first one. The only way to merge is to use Terminal or an external tool.
If your Finder window with Details view is packed with files, you can’t create a new folder with the right click menu unless you either enlarge the window, to get space below the files where a right click have New Folder command or use shortcut/main menu. On Windows - right click would work after the last column because a files don’t spread over an entire line.
In details view, with a tree of files opened (great feature!), when pasting a file it’ll paste it to the top most directory you’re in, and not the one you marked.
In native apps, if a text field is disabled, you can’t select the text in it at all.
Several applications require you to right click on their dock icon in order to open them. For example, Adium: when the contact list is closed and there’s a conversation opened. True, it’s also Adium’s fault, but it’s more a window management UI issue.
Deleting a file on the Finder (cmd+Backspace) clears the selected file. If you want to go to the next file with the down arrow - it’ll start from the first file on the top of the list. It should remember the location of the last deleted file and focus on the one that was next to it (or previous if it’s the last file).
You must use Terminal for lots of advanced configurations. They don’t appear on System Preferences. Things like “Show hidden files” and more.
No editable address bar in finder. ‘Go to Folder’ doesn’t count. It would, if it was showing the full current address of a window, but it shows only the last accessed path. Again, only terminal can make things easier.
The Preview application won’t let you navigate through files in the same directory, unless they were all opened together initially.
Weird and inconsistent Home & End buttons. I want it to go to the beginning/end of a line and not the top of the document. Several applications use the first approach and others use the second one. Solution: KeyFixer
No Right-Click+Dragging (used for copy/move/extract etc.)
Cmd+N in a Finder window opens the home directory. But most of the times I used it, I meant to duplicate the same window. Solution: TotalFinder
Windows are resizable only from one corner. That means, that if a window is “stuck” on a size that is bigger than the screen, it cannot be resized, and you’re probably doomed, because most apps remember their size/location. It happend to me more than once after plugging off an external screen. Solution: Divvy
I guess that most of the users don’t need all of these, but I’m sure I’m not the only one complaining about them. Apple might want to protect the general users, and their approach seems like “We are way smarter than you”. But why don’t they create “Advanced Mode” for developers and advanced users?
I still use it because of the full native support for Ruby on Rails, Apache, iPhone development and such, but sometimes, I miss Windows 7.