@brunofuster

www.wesaveapp.com

scaling sessions properly on express

leave a comment »

When using sessions on Express you should be careful. The default behavior with app.use(express.session()) is to save the session on any response even if you don’t need it.

From ExpressJS docs:

Properties on req.session are automatically saved on a response

First of all: Redis

Instead of using the default in-memory implementation from Connect, you should start by using a distributable in-memory storage like Redis.

Redis To Go has a free 5MB plan if you want to get started on the cloud.

$ npm install connect-redis

var RedisStore = require('connect-redis')(express)
  , session_store = new RedisStore({host: 'redistogo.com', port: 6379, pass: 'password', prefix: 'appsess:'});

var session = function() {
  return express.session({ store: session_store, secret: 'salt' });
}


Default but wrong usage

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(session());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

Now use apache bench to stress test your unlogged home page:
$ ab -r -n 5000 -c 50 http://127.0.0.1/

Redis should now have 5000 leaked keys waiting for its expiration, consuming huge amount of unnecessary memory.



Per-request session: the real deal

Just load and save the session object when you really need!

Remove app.use(session()) from app.configure!

//without session
app.get('/', function(req,res) {}); 

//with session
app.get('/admin', session(), function(req, res) {});

Delete all Redis keys.
Run the apache bench command again and check your Redis memory totally unused.

Written by brunofuster

June 21, 2012 at 6:56 pm

Posted in cloud, expressjs, redis

Kiwi: Simple BDD for iOS

leave a comment »

Github

https://github.com/allending/Kiwi

Docs

https://github.com/allending/Kiwi/wiki

Screencast

http://nsscreencast.com/episodes/4-automated-testing-with-kiwi/play

Code sample

describe(@"Team", ^{
    context(@"when newly created", ^{
        it(@"should have a name", ^{
            id team = [Team team];
            [[team.name should] equal:@"Black Hawks"];
        });

        it(@"should have 11 players", ^{
            id team = [Team team];
            [[[team should] have:11] players];
        });
    });
});

Written by brunofuster

February 28, 2012 at 5:27 pm

Posted in Uncategorized

xcode 4 storyboard resources

with 2 comments

Written by brunofuster

February 14, 2012 at 11:58 pm

Posted in iOS, objective-c

deploying a node.js project on cloudfoundry (mac osx)

leave a comment »

If you don’t have your cloudfoundry credentials create here: www.cloudfoundry.com

I’ve run into a bug using Mac’s ruby. If you already use rvm and ruby 1.9.2, you can skip the first step. Found the bug solution here.

Setting up Ruby

Install rvm:

$ bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )

Add the following lines to ~/.bash_profile

# Ruby Version Manager
[[ -s "$HOME/.rvm/scripts/rvm" ]] && . “$HOME/.rvm/scripts/rvm”

Update your terminal env with source or open a new terminal

$ source ~/.bash_profile

Now install ruby 1.9.2

$ rvm install 1.9.2
$ rvm use 1.9.2

Configuring cloudfoundry

Install the vmc gem

$ gem install vmc

Set the target

$ vmc target api.cloudfoundry.com

Login with your credentials… vmc will ask for your email and password.

$ vmc login

Creating a simple express app

* You need Node.JS and NPM from now on

$ sudo npm install express jade
$ mkdir sample-project
$ cd sample-project
$ express

Start your app to check its running:

$ node app.js

Open http://localhost:3000 and see the Welcome to Express msg :)

Configuring your app to run on cloudfoundry

Install cloudfoundry module

$ npm install cloudfoundry

Change your app.js to run locally and at the cloudfoundry

$ vi app.js

Require the cloudfoundry module

var cloudfoundry = require(‘cloudfoundry’);

Go to the app.listen line at the end of the file and change to:

app.listen((cloudfoundry.port || 3000), (cloudfoundry.host || ‘localhost’));

Create a file called package.json and put the used modules:

*jade is the view engine

{
    “name”:”sample-app-bfuster”,
    “version”: “0.0.1”,
    “dependencies”: {
        “express”:””,
        “cloudfoundry”:””,
        “jade”:””
    }
}

Bundle those modules into your project

$ npm bundle

Deploy your app

$ vmc push

Console output:

Would you like to deploy from the current directory? [Yn]: y
Application Name: sample-app-bfuster
Application Deployed URL: ‘sample-app-bfuster.cloudfoundry.com’?
Detected a Node.js Application, is this correct? [Yn]: y
Memory Reservation [Default:64M] (64M, 128M, 256M, 512M or 1G)
Creating Application: OK
Would you like to bind any services to ‘sample-app-bfuster’? [yN]: n
Uploading Application:
  Checking for available resources: OK
  Processing resources: OK
  Packing application: OK
  Uploading (33K): OK
Push Status: OK
Staging Application: OK
Starting Application: OK

Running app: http://sample-app-bfuster.cloudfoundry.com
source: https://github.com/bfuster/cf-sample-app

Written by brunofuster

October 27, 2011 at 11:54 am

Wesave, save money and help others save too!

leave a comment »

Hi! I’ve been working hard on my first iphone app for the past year with some friends: Andre Gil, Beck Novaes and Eduardo Horvath.

We hope you enjoy and make use of it! Feel free to send us your feedback at team@wesaveapp.com!

Check it out! Wesave is a really cool app!

www.wesaveapp.com or you can install it right away on the AppStore

Video

Screenshots

Written by brunofuster

October 26, 2011 at 10:09 pm

uploading an image from iphone to appengine blobstore using vraptor

with 7 comments

Its quite simple to do this. I will represent the back-end using vraptor, a really great mvc web framework.

Well, at first, you need to generate the upload URI, provided by GAE’s SDK. When you’re working with web forms, you can just call the BlobstoreService to create the Upload URI directly from your JSP, but this is not the case.

We will provide then a resource that will return an URI for the upload.


@Resource
@Path("/image")
public class ImageController {

    private final BlobstoreSevice blobstoreSevice = BlobstoreServiceFactory.getBlobstoreService();
    private final Result result;

    public ImageController(Result result) {
        this.result = result;
    }

    @Path("/createUploadURI")
    public void uploadURI() {
        
        String uploadURI = blobstoreService.createUploadUrl("/image/upload");
        result.use(http()).body(uploadURI);
    }

}

That’s enough to return the upload URI into the response body (we wont use json or xml at this time to simplify the post).
Just for the record, there’s an issue when running this at development server. Blobstore won’t return the URI with its host, although it will return the absolute URI when at production environment.

Lets consume this resource from iphone now using asihttp.

#import "ASIHTTPRequest.h"
//...

-(void) getUploadURI {

	NSURL *uri = [NSURL URLWithString:@"http://yourserver.appspot.com/image/createUploadURI"]];
	ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:uri];
	[request setDelegate:self];
	[request startAsynchronous];
}

-(void) requestFinished:(ASIHTTPRequest *)request {

	NSString *uri = [request responseData];
}

-(void) requestFailed:(ASIHTTPRequest *)request {
	
	NSError *error = [request error];
	NSLog(@"error %@", error);
}

Now we have the URI to upload an image. Lets create a new objective-c class to handle the upload using asihttp form data (notice that we will also track the upload progress).

#import <Foundation/Foundation.h>
#import "ASIFormDataRequest.h"

@interface ImageUpload : NSObject {

	ASIFormDataRequest *formData;
	float progress;
}

@property (nonatomic, retain) ASIFormDataRequest *formData;
@property (nonatomic, assign) float progress;

-(id) initWithImage:(UIImage*)img uri:(NSString*)uri;
-(void) startUpload;

@end

And it’s implementation:

#import "ImageUpload.h"

@implementation ImageUpload

@synthesize formData, progress;

-(id) initWithImage:(UIImage*)img uri:(NSString*)uri {
	
	NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(img)];

	self.formData = [[ASIFormDataRequest requestWithURL:[NSURL URLWithString:uri]] retain];	
	[self.formData setData:imageData withFileName:@"defaultImage.png" andContentType:@"image/png" forKey:@"defaultImage"];
	[self.formData setDelegate:self];
	[self.formData setUploadProgressDelegate:self];
	
	return self;
}

-(void) startUpload {

	[self.formData startAsynchronous];
}

#pragma mark Upload Progress Tracking

- (void)request:(ASIHTTPRequest *)theRequest didSendBytes:(long long)newLength {
	
	if ([theRequest totalBytesSent] > 0) {
		float progressAmount = (float) ([theRequest totalBytesSent]/[theRequest postLength]);
		self.progress = progressAmount;
	}
	
}

-(void) requestFinished:(ASIHTTPRequest *)request {
	NSLog(@"upload finished");
}

-(void) requestFailed:(ASIHTTPRequest *)request {
	NSError *error = [request error];
	NSLog(@"error %@", error);
}

- (void) dealloc
{
	[self.formData release];
	[super dealloc];
}
@end

Let’s change the requestFinished: method for /image/getUploadURI to start the upload after its response is done.

#import "ImageUpload.h"
//...
-(void) requestFinished:(ASIHTTPRequest *)request {

	ImageUpload *imageUpload = [[ImageUpload alloc] initWithImage:self.imageView.image uri:[request responseData]];
	[imageUpload startUpload];
}

If you want to track the progress at this view, you can create your own delegate like [imageUpload setUploadTrackingProgress:self] or expose the asihttp method setUploadProgressDelegate:.

At last we will create the resource that Blobstore will call on your server after the upload has been completed. You can now use the Images Service to get an URI for this image and store it.

@Path("/upload")
public void upload() {
	Map<String, BlobKey> blobs = blobstoreService.getUploadedBlobs(request);
	BlobKey blob = blobs.get("defaultImage");
		
	ImagesService imagesService = ImagesServiceFactory.getImagesService();
	String imageUrl = imagesService.getServingUrl(blob);

	/* datastore.put(imageurl) */
	result.use(Results.http()).body(imageUrl);
}

We just need to inject the current HttpServletRequest for the BlobstoreService like this:

@Resource
@Path("/image")
public class ImageController {

    private final BlobstoreSevice blobstoreSevice = BlobstoreServiceFactory.getBlobstoreService();
    private final HttpServletRequest request;
    private final Result result;

    public ImageController(Result result, HttpServletRequest request) {
        this.result = result;
        this.request = request;
    }
...

References:
vraptor
asihttp
Blobstore Service
Images Service
http://ikaisays.com/2010/09/08/gwt-blobstore-the-new…

Written by brunofuster

March 11, 2011 at 3:06 pm

restfulie-objectivec simple post, http response codes and basic auth

leave a comment »

Now restfulie-objectivec is using by default ASIHTTP. Its too coupled by now, but I’m working on this and you will be able to extend it and use any http lib.

You can now call a simple http post method, without a payload. I’m working on the JSON marshaller and it will be ready soon.


Response *response = [[[client at:@"http://localhost:8888/login"] authUser:@"login" andPassword:@"passwd"] post];

if (response.code == 200) {
    NSLog(@"login success");
} else {
    NSLog(@"login fail");
}

Written by brunofuster

January 16, 2011 at 5:45 pm

Follow

Get every new post delivered to your Inbox.