=head1 NAME

Ref::Store::Walkthrough - Walkthrough on how to rewrite a module
using Ref::Store

This document is to supplement the synopsis
in the main module docuemntation.

We will try to dissect and pseudo-refactor
the code in L<POE::Component::Client::HTTP> (refered to as poco-http)
to demonstrate the usefulness of this module.

We will assume that there is a gloabl object, <$Table> which may presumably be
stored on the I<heap>

We have a bunch of key types, so let's register them.

	my @KEY_TYPES;
	BEGIN {
		 @KEY_TYPES = map 'KT_'.$_, (
		 
			"EXT_REQ", #HTTP::Request object
			"POE_REQ", #POE::Component::Client::HTTP::Request object
			"POE_REQID", #ID of the POE request
			"POE_WID", #POE::Wheel ID, needed for events.
			
		);
		
		foreach my $kt (@KEY_TYPES) {
		   no strict 'refs';
		   *{$kt} = sub () { $kt }
		}
	}
	
	#....
	#Assume a table has been created by now
	$Table->register_kt(@_)  foreach (@KEY_TYPES);
	
The poco-http API takes a request object and optionally accepts a tag, by which
the user can easily identify the response received. The prime internal identifier
used by POE is an internal Request object (C<POE::Component::Client::HTTP::Request>),
identified by its refaddr:

	my $request = $heap->{factory}->create_request(
	  $http_request, $response_event, $tag, $progress_event,
	  $proxy_override, $sender
	);
	$heap->{request}->{$request->ID} = $request;
	$heap->{ext_request_to_int_id}->{$http_request} = $request->ID;

Instead of the last two lines, we do:
	
	$Table->store_kt($request->ID, KT_POE_REQID, $request, StongValue => 1);
	#Because this is our primary reference.
	$Table->store_kt($http_request, $request);
	
Later on, in the same function, we have this code:
	
	if ($@) {
		delete $heap->{request}->{$request->ID};
		delete $heap->{ext_request_to_int_id}->{$http_request};
	
		# we can reach here for things like host being invalid.
		$request->error(400, $@);
	}
	
Which can be refactored to:

	$Table->purge($request);

Which will clean up everything associated with $request.

At this point, poco-http has submitted a request to its connection manager
(L<POE::Component::Client::KeepAlive>), and is now awaiting a response. Here is
the code which handles it, with ommisions not pertinent to the description of the
Ref::Store module.

	sub _poco_weeble_connect_done {
	  my ($heap, $response) = @_[HEAP, ARG0];
	
	  my $connection = $response->{'connection'};
	  my $request_id = $response->{'context'};
		
	  if (defined $connection) {
		DEBUG and warn "CON: request $request_id connected ok...";
		
		#my $request = $heap->{request}->{$request_id};

Nothing revolutionary here, replace with:
		
		my $request = $Table->fetch_kt(KT_POE_REQID, $request_id);
		
		unless (defined $request) {
		  DEBUG and warn "CON: ignoring connection for canceled request";		  
		  return;
		}
	
		my $block_size = $heap->{factory}->block_size;
	
		# get wheel from the connection
		my $new_wheel = $connection->start(
		  Driver       => POE::Driver::SysRW->new(BlockSize => $block_size),
		  InputFilter  => POE::Filter::HTTPHead->new(),
		  OutputFilter => POE::Filter::Stream->new(),
		  InputEvent   => 'got_socket_input',
		  FlushedEvent => 'got_socket_flush',
		  ErrorEvent   => 'got_socket_error',
		);
	
		DEBUG and warn "CON: request $request_id uses wheel ", $new_wheel->ID;
	
		# Add the new wheel ID to the lookup table.
		
		#$heap->{wheel_to_request}->{ $new_wheel->ID() } = $request_id;
		
And instead of this construct, we use:

		$Table->store_a($new_wheel->ID(), KT_POE_WID, $request);

We skip a bunch of SSL initialization code, since it does not seem to use
any type of lookup

	else {
		DEBUG and warn(
		  "CON: Error connecting for request $request_id --- ", $_[SENDER]->ID
		);
	
		my ($operation, $errnum, $errstr) = (
		  $response->{function},
		  $response->{error_num} || '??',
		  $response->{error_str}
		);
	
		DEBUG and warn(
		  "CON: request $request_id encountered $operation error " .
		  "$errnum: $errstr"
		);
	
		DEBUG and warn "I/O: removing request $request_id";

		#my $request = delete $heap->{request}->{$request_id};
		#$request->remove_timeout();
		#delete $heap->{ext_request_to_int_id}->{$request->[REQ_HTTP_REQUEST]};


Is replaced with:

		$Table->purge($request);
		$request->remove_timeout();

Here is the timeout function:

	sub _poco_weeble_timeout {
	  my ($kernel, $heap, $request_id) = @_[KERNEL, HEAP, ARG0];
	  
	  #my $request = delete $heap->{request}->{$request_id};
	  
Instead, we delete ALL lookup data associated with the key by doing this:

	  my $request = $Table->purgeby_kt($request_id, KT_POE_REQID);
	  ...
	  
We don't need this line

	  delete $heap->{ext_request_to_int_id}->{$request->[REQ_HTTP_REQUEST]};
	  ...
	  
Nor do we need this

		delete $heap->{wheel_to_request}->{$wheel_id};
		...

etc. etc.
The rest of the POE code is more or less the same.

Look here for some other code which could use an even better helping of this
module.

