[Dancer-users] Follow-up: mysterious behavior putting Dancer app in production on Starman

Mr. Puneet Kishor punk.kish at gmail.com
Sun Jul 17 19:18:25 CEST 2011


Top posting a solution --

I think I may have found a reason and a (temporary) solution. Actually, I didn't find it, but a helpful person at Stackoverflow suggested that I may be creating a $dbh that might be getting shared by different Starman preforked children (see link below). I think that was the case. I am still testing it by moving the $dbh creation in the subs.

http://stackoverflow.com/questions/6721057/asynchronous-queries-with-mysql-perl-dbi

So, instead of

	package mypackage;
	use Dancer ':syntax';
	use DBI;
	
	my $dbh = DBI->connect("..");
	
	get '/' => sub { template 'index'; };
	
	get '/points.:format' => sub {
		my $bbox = params->{'BBOX'};
		my $callback = params->{'callback'};
		return $callback . '(' . to_json(points_within_bbox($bbox)) . ')';
	};
	
	get '/polys.:format' => sub {
		my $bbox = params->{'BBOX'};
		my $callback = params->{'callback'};
		return $callback . '(' . to_json(polys_within_bbox($bbox)) . ')';
	};
	
	sub points_within_bbox {
		my ($bbox) = @_;
		
		my $sth = $dbh->prepare("..");
		$sth->execute($bbox);
		return $sth->fetchall_arrayref({});
	}
	
	sub polys_within_bbox {
		my ($bbox) = @_;
		
		my $sth = $dbh->prepare("..");
		$sth->execute($bbox);
		return $sth->fetchall_arrayref({});
	}

I now do the following 

	package mypackage;
	use Dancer ':syntax';
	use DBI;
	
	get '/' => sub { template 'index'; };
	
	get '/points.:format' => sub {
		my $bbox = params->{'BBOX'};
		my $callback = params->{'callback'};
		return $callback . '(' . to_json(points_within_bbox($bbox)) . ')';
	};
	
	get '/polys.:format' => sub {
		my $bbox = params->{'BBOX'};
		my $callback = params->{'callback'};
		return $callback . '(' . to_json(polys_within_bbox($bbox)) . ')';
	};
	
	sub points_within_bbox {
		my ($bbox) = @_;
		
		my $dbh = DBI->connect("..");
		my $sth = $dbh->prepare("..");
		$sth->execute($bbox);
		return $sth->fetchall_arrayref({});
	}
	
	sub polys_within_bbox {
		my ($bbox) = @_;
		
		my $dbh = DBI->connect("..");
		my $sth = $dbh->prepare("..");
		$sth->execute($bbox);
		return $sth->fetchall_arrayref({});
	}

It seems to be holding up. I am going to add another web service to the app, and see if it works.


On Jul 16, 2011, at 8:05 PM, Mr. Puneet Kishor wrote:

> Following with more investigation and observation (please see below) --
> 
> On Jul 15, 2011, at 9:07 AM, Mr. Puneet Kishor wrote:
> 
>> 
>> On Jul 14, 2011, at 8:55 PM, Mr. Puneet Kishor wrote:
>> 
>>> Check out the following [http://teststrata.geology.wisc.edu/macromap]. It should be working -- it should show a Google map backdrop with a bunch of polygons and a few points. As you pan and zoom, polys and points for the new viewport should be retrieved.
>>> 
>>> The polys and points are retrieved via ajax from [http://teststrata.geology.wisc.edu/mstrat/] that is serving them from a MySQL db as a REST service.
>>> 
>>> Both apps are Dancer based, and are running on Starman using the following invocation
>>> 
>>> $ plackup -p <port> -E production -s Starman -w 10 -a bin/app.pl
>>> 
>>> The first app (macromap) also has the -D switch added to the above plackup command so plackup runs in the background as a daemon (or a faceless app, or whatever is the correct terminology).
>>> 
>>> Here is the interesting thing -- if I add the -D switch to the second app as well, it fails to return the polys and the points. It fails with the error
>>> 
>>> {"error":"Warning caught during route execution: DBD::mysql::st fetchall_arrayref failed: fetch() without execute() at <path/to>/macrostrat.pm line 79.\n"}
>>> 
>>> The offending lines are
>>> 
>>> 	71> my $sql = qq{
>>> 	72> 	..
>>> 	73>
>>> 	74>
>>> 	75> };
>>> 	76> 
>>> 	77> my $sth = $dbh->prepare($sql);
>>> 	78> $sth->execute();
>>> 	79> my $res = $sth->fetchall_arrayref({});
>>> 
>>> The above could be just correlation rather than causal, but it definitely seems to be a pattern. First, this is bizarre, and why so? And, two... this is totally bogus... how can execute() not take place above? Perl doesn't have a habit of jumping over lines, does it?
>>> 
>>> Absolutely mystified in Madison.
>>> 
>> 
>> 
>> Following Paul Findlay's advice, I launched my offending app with the following invocation
>> 
>> 	$DBI_TRACE=2=logs/dbi.log plackup -E production -p 5001 -s Starman -w 10 -a bin/app.pl
>> 
>> And, following is what stood out to me as the potential culprit in the log file
>> 
>> 	> Handle is not in asynchronous mode error 2000 recorded: Handle is 
>> 	> not in asynchronous mode
>> 	>    !! ERROR: 2000 CLEARED by call to fetch method
>> 
>> 
>> (I am shooting in the dark here) I believe Dancer uses a lot of global variables. Would that be connected to this error? On occasion, I am also seeing another mysterious behavior, so mysterious that I feel I am smoking something --
>> 
>> One request to the web server pulls in points, and another request pulls in polys. They are called like so
>> 
>> 	http://webserver/points.json
>> 	http://webserver/polys.json
>> 
>> They are both separate asynchronous requests, sent via separate $.ajax() jQuery calls from the browser. On occasion, and I swear I am not making this up, I see points json stream returned via the polys request. Of course, because points.json returns different data than polys.json, I get an error.
>> 
>> For what its worth, and this is highly unscientific, this doesn't happen if plackup is in `-E development` mode. It only happens in the `-E production -D` mode. But, I could be wrong about this as I don't have a large enough sample set to confirm this finding conclusively.
>> 
>> Thoughts?
>> 
> 
> A simple script like so works like a champ... no async nonsense, no errors. All 1000 requests are effortlessly returned by the same set up.
> 
>    use LWP::UserAgent;
> 
>    my $BBOX = "-96.09299316406248+38.96034339396338%2C+83.39279785156248+38.96034339396338%2C+-83.39279785156248+44.33256692562997%2C+96.09299316406248+44.33256692562997%2C+-96.09299316406248+38.96034339396338";
> 
>    for (1 .. 1000) {
> 	open my $fh, ">>", 'foo.txt';
> 	
> 	my $ua = LWP::UserAgent->new;
> 	$ua->agent("MyApp/0.1 ");
> 	
> 	my $req = HTTP::Request->new(GET => "http://localhost:5001/points.json?callback=foo&BBOX=$BBOX");
> 	my $res = $ua->request($req);
> 	
> 	# Check the outcome of the response
> 	if ($res->is_success) {
> 		say $fh $res->content;
> 	}
> 	else {
> 		say $fh $res->status_line;
> 	}
> 	
> 	close $fh;
>    }
> 
> So, it seems that both MySQL and Starman are very capable of handling this. The only element missing here is Dancer, and the browser. Thoughts anyone? I am just interested in finding out the issues here, and creating a robust, workable app.
> 
> Many thanks in advance.
> 
> Puneet.



More information about the Dancer-users mailing list