Archive for the ‘Programming’ Category

h1

Lighting the tunnErl Pt 6 – Using Mochiweb for Chatterl’s RESTful API

January 15, 2009

This post is the next in the ‘Lighting the tunnErl‘ series, documenting my experiences with Erlang as I learn it and its tools, as the previous post focused on Faxien & Sinan, I decided to concentrate on working with yaws or Mochiweb. As I’m still actively working on Chatterl, which as mentioned here, is a multi-node chat system, and it needed a web interface, I did some research and decided to use Mochiweb, though the part six was originally going to be ‘Erlang Gotchaz’, I thought I should post this first whilst the information is still fresh in my mind.

General overview

I recently started to play around with Mochiweb & BeepBeep to see what functionality they could provide Chatterl, after a couple of days working around the BeepBeep’s code, I decided to focus on the actual gateway API (CWIGA) and use Mochiweb along with a little manipulation to create the gateway service that would in turn serve the frontend which will use BeepBeep to render the data. A bit convoluted maybe but I want other to be able to use the backend separately and plug in their own frontends ;) , not to mention it’s an excellent chance to play with new toys.

The foundations weren’t that hard to put together, think it took all of 2 minutes to get Mochiweb running, setting up the basics are just that & simple interactions with other systems is straight forward. Though saying that I quickly found that one can encounter some serious head banging moments with Mochiweb especially with the lack of documentation at present.

I also feel Mochiweb lacks fundamental features like destroying cookies, manipulating headers/query string & the such like a lot of this is left down to the developer, which in my opinion isn’t ideal, I’d rather spend time on the problem at hand rather than deal with mini side effects.

I really really hate pros/cons, loves/hates, but hell I really do have a love/hate relationship with Mochiweb at the moment, I’m hoping that this is just part of the curve but I have to admit it certainly is an interesting beast.

Loves

  • Quick & easy to initialise Mochiweb.
  • Initialising cookies is simple.
  • Fully customisable
  • Setting up basic handling is easy.
  • Is fast and lightweight.

Hates

  • No encryption methods.
  • Fully customisable.
  • No real work examples.
  • Converting content body has to be done manually.
  • Isn’t well documented.

The past week has had a lot of ups & downs in regards to Mochiweb, after a week of tinkering, I have finally finished the crux of CWIGA (Chatterl’s Web Interface Gateway API) & generally enjoyed working with Mochiweb & will utilise it for the front-end of Chatterl integrated with BeepBeep, which will deal with cookie management.

Ok, with the mini review over with, here’s some info on how I’m using Mochiweb at the moment, the source code and be found here.

Initialising Mochiweb

init([Port]) ->
    io:format("Initialising Chatterl Web Interface~n"),
    process_flag(trap_exit, true),
    mochiweb_http:start([{port, Port}, {loop, fun dispatch_requests/1}]),
    erlang:monitor(process,mochiweb_http),
    {ok, #state{}}.

Excerpt taken from a init method, here we initialise the gen_server, as the gen_server has a supervisor we use trap_exit, just below is our call to initialise Mochiweb, where we pass it the port {port, Port} & tell it what function to pass the request to (dispatch_requests).

Dispatching requests

Now we need to be able to handle all our request, to do this we use the following method:

dispatch_requests(Req) ->
    [Path|Ext] = string:tokens(Req:get(path),"."),
    Action = clean_path(Path),
    handle(Action,Ext,Req).

As I want to know what the extension type was requested (so that we can respond with the appropriate format) we split the request path using tokens and supplying ‘.’ as the parameter, this way URL like http://127.0.0.1:9000/controller/action.xml our Ext will store ‘xml’.

We then clean the path using clean_path, which will be discussed next to determine the Action we want to carry out. We then have all we need to handle our requests.

Cleaning paths

clean_path(Path) ->
    case string:str(Path, "?") of
	0 ->
	    Path;
	N ->
	    string:substr(Path, 1, string:len(Path) - (N + 1))
    end.

Here all we want is the actual path to the quest ‘/some/action/here’, so we check to see if there is a ‘?’, if so return everything preceding it, otherwise we return the path, that simple really. Though having said that, I’m sure this type of functionality should be in Mochiweb (one day eh, it’s still not production ready).

Handling requests

Now this is the fun bit, I’m going to delve into building JSON structures to use as response, purely as this one as serious pain in the ass to implement & hardly documented online.

handle("/connect/" ++ Client,ContentType,Req) ->
    {Type,Record} =
    case gen_server:call({global,chatterl_serv},{connect,Client}) of
	{ok,_} -> {"success",Client++" now connected"};
	{error,Error} -> {"failure",Error}
    end,
    send_response(Req,{get_content_type(ContentType),build_carrier(Type,Record)});

Now this method took a little while to structure properly and can look a little daunting, lets walk through it’s purpose.

So our handle method needs to be able to make calls to Chatterl and build the appropriate response using records (carriers). each response has a type which determine the type of response to return (success/failure) here we can respond with the appropriate HTTP response code (200/401,etc). We also need the actual response data (Record) which is packaged and returned in a Tuple ({Type,Record}) along with the response type. These pieces of data are then sent off to send_response (send_response(Req,{get_content_type(ContentType),build_carrier(Type,Record)}); which will be explained shortly. Before that there are two methods that need to be explained, get_content_type & build_carrier. The former is a simple wrapper which returns a record with the record type (“success”) & message (“user joined”). Where as the former passes the desired content type (Ext) and receives the appropriate content type contents:

get_content_type(Type) ->
    case Type of
	["json"] ->
	    "text/plain";
	["xml"] ->
	    "text/xml";
	_ -> "text/plain"
    end.

As mentioned earlier I want to be able to respond in either JSON or XML, with this method we are able to pass the type (remember Ext?) and return the correct content type. As I prefer JSON I’ve implemented that as the default.

Sending responses

Now here is where it starts to get interesting, we have our content type along with our results & response type, we now need to find out what type of response we have and build the appropriate format (JSON/XML).

send_response(Req, {ContentType,Record}) when is_list(ContentType) ->
    Response = get_response_body(ContentType,Record),
    Code = get_response_code(Record),
    Req:respond({Code, [{"Content-Type", ContentType}], list_to_binary(Response)}).

Now this method is pretty simplistic, though a lot of work is being done by get_response_body, We basically retrieve our formatted response, then get the appropriate response code, then we shuttle the data off to the client. Job done.

Building response bodies

Here we want to know what type of response we should contruct, once doing so, build & return the response.

get_response_body(ContentType,Record) ->
    case ContentType of
	"text/plain" ->
	    json_message(Record);
	"text/xml" ->
	    xml_message(Record);
	_ -> json_message(build_carrier("error","Illegal content type!"))
    end.

Next we need to correct response code:

get_response_code(Record) ->
    case Record of
	{carrier,Type,_Message} ->
	    case Type of
		"failure" -> 200;
		"success" -> 200;
		"error" -> 500;
		_ -> 500
	    end
    end.

As all errors and unknown responses shouldn’t happen we want to our response code to return 500 in those cases, otherwise return with a 200.

Now this is where it gets fun & where I still need to iron some things out, ideally I have a message_body method passing an atom (JSON/XML & the data) and returning the appropriate data. Below I will go into my current solution.

Building JSON

I have to say construction response can be quite a pain in Erlang, I’d suggest doing the thing I haven’t, test your patterns. One day I’ll starting testing my Erlang code as vigously as the rest of my code.

Ok back on track, so we need to one generate three types of carrier (groups,clients & messages), if the type passed doesn’t exist we print a message on the node (ideally the client should get some kind of error, I have yet to implement this yet though). Otherwise the helper method (handle_messages_json) is called and the results are injected into the outter structure ({struct,[{chatterl,{struct,[{response,Struct}]}}]})which in turn is passed to mochijson2 for conversion.

json_message(CarrierRecord) ->
    {carrier, CarrierType, Message} = CarrierRecord,
    Struct =
	case Message of
	    {carrier,Type,MessagesCarrier} ->
		case Type =:= "groups" orelse Type =:= "clients" orelse Type =:= "messages" of
		    true ->
			handle_messages_json(Type,MessagesCarrier,CarrierType);
		    false ->
			io:format("dont know ~s~n",[Type])
		end;
	    _ ->
		{struct,[{CarrierType,list_to_binary(Message)}]}
	end,
    mochijson2:encode({struct,[{chatterl,{struct,[{response,Struct}]}}]}).

Now we have differing types of carriers so here we need to check what we have and deal with it appropriately, for this post we will just focus on handling our JSON responses. Just past the case statement which checks that our carrier type is either a groups, client or messages we send the Type, along with the Carrier (holding the actual data) & the carrier type (storing which type of carrier we are handling). Once the results are back from handle_responses_json, they are inserted into a wrapper structure which is in turn used to create the whole JSON body:

{"chatterl":
	{"response":
		{"success":
			{"groups":[
				{"group":"nu_group"},
				{"group":"anuva_group"},
				{"group":"one_more"}
			]}
		}
	}
}

Handling JSON responses

handle_messages_json(Type,MessagesCarrier,CarrierType) ->
    case Type =:= "messages" of
	true ->
	    case MessagesCarrier of
		[] -> %Empty list.
		    {struct,[{Type,[]}]};
		[{carrier,_MessageType,MessageData}] ->	% A Single message.
		    {struct,[{CarrierType,
			      {struct,[{Type,loop_json_carrier(MessageData)}]}}]};
		Messages -> % Multiple messages
		    {struct,[{CarrierType,
			      {struct,[{Type,inner_loop_json_carrier(Messages)}]}}]}
	    end;
	false ->
	    {struct,[{CarrierType,{struct,[{Type,loop_json_carrier(MessagesCarrier)}]}}]}
    end.

As mentioned earlier we have three type of responses, empty, singular & multidimensional. In this method we work out what type of response structure we have and construct the appropriate JSON structure for it. We need another helper here mainly for building our structured responses, which is where loop_json_carrier & inner_loop_json_carrier comes in handy (code shown below). They basically iterate over the response carrier. Once complete it wraps this structure up in another which stores the carrier & response types.

loop_json_carrier(CarrierRecord) ->
    [{struct,[{list_to_binary(DataType),clean_message(Data)}]} || {carrier,DataType,Data} <- CarrierRecord].
inner_loop_json_carrier(CarrierRecord) ->
    [{struct,[{list_to_binary(MsgType),loop_json_carrier(Msg)}]} || {carrier,MsgType,Msg} <- CarrierRecord].

Now this methood isn’t ideal I’m sure that I can improve these methods but to be honest I’ve been working tirelessly on this & decided to leave it as something else to work out. The latter loops over each carrier in turn alling loop_json_carrier & wrapping the result in a struct tuple. The former method does more aless the same functionality apart from it cleans the message body using the clean_message/1 method.

clean_message(Data) when is_tuple(Data) ->
    {A,B,C} = Data,
    [A,B,C];
clean_message(Data) ->
    list_to_binary(Data).

We’ll I use this as a wrapper to clean up responses, ideally you could convert data to UTF-8 list_to_atom, what ever you fancy. I’m presently using it to clean Erlang dates (as I’ve not worked out how to convert them properly yet) & lists into binary.

Summary

Well thats basically it for now. I’ve left out XML parsing partly as I haven’t have the time to implemented parsing multidimensional structures yet & the code can be found here for those who are really curious ;) .

I will say this though working with XML in Erlang is probably one of the most unpleasant experiences for me at the moment. All in all Mochiweb is a nice powerful tool, it still has a lot of growing to do but it is definitely a shining example of what can be done with Erlang, hopefully more documentation will enter the wild & we will see it hosting a number of services in the future.

h1

Lighting up the TunnErl Pt. 5 – The LightErls

January 9, 2009

Well what was initially one past has turned into a good few, they seem to be popular & I’ve had this in the drafts for the past week, this one focuses more on handling builds and the issues I’ve come across doing so, with a focus on what Faxien & Sinan have to offer.

Getting off the stumbling blocks
After a couple week of tinkering (ages by my standards), I had a simple Twitter interface that could run from the shell.

Though Twitterl is far from perfect, it was a good starting point, there were still things missing from my skill set:

  • A simple way to manage the application
  • How to make OTP compatible
  • How to create an application that can run from a bash shell
  • Handle documentation for projects.

How kill a few birds with one stone
Well for this I had to do a little reading and knew how to make a basic gen_server, what I needed for Chatterl was a number of gen_servers controlled by supervisors, which are encapsulated by an outer supervisor which handles the main application.

I decided for this it would be a good idea to start a new project, something I’ve wanted to create for some time, hence Chatterl, when learning I feel it makes sense to learn whilst working (I’ve worked on a number of chat systems so making a multi-node version is definitely compelling).

This project was not only something that I wanted to build for practical use but also to help me delve into Faxien & Sinan, which will help to kill a few birds at the same time.

I hate hackish code, its fine for playing around but if you want to upgrade/remove or search for applications, its a pain in the arse. So after some reading, I installed Faxien.

Now I’m not going to rewrite Sinan documentation it is pretty decent as is & there is already a decent post here, but I will give you a run down of the basics.

Now I decided to use Faxien & Sinan for a number of reasons, it saves when it comes to generating the files nessary for creating our OTP stucture. Faxien will help us install our project into our include path ‘/usr/local/erlware’, whilst Sinan will help generate our project, handle the builds and run tests and analytics on our project.

The following commands are what I seem to use the most at the moment:

  • sinan gen
  • sinan build
  • sinan dist
  • sinan test
  • faxien install-release
sinan gen

Allows us to generate the base code needed to create an OTP based application, I use this to generate a project skeleton, saving time in messing around with make files and the such like. There is no need to end the command with the project name as this and other pertaining data will be requested within the followed prompt.

sinan build

Allows us to build the application when we have made changes, simply run this from the root of the project directory and Sinan will handle building the application for you (note this does not build the documentation).

sinan doc

This will build all the documentation for our project, see edocs for more information, one thing I will mention, seeing as it took me a while to work out, the edocs overview.edoc is located with project/lib/src/PROJECT/doc. Simply write up our application documentation within that file and it will be generated with the rest of your source documentation.

sinan dist

Builds our application and creates the release tar for us, which is stored in _build/development/tar.

sudo faxien install-release _build/development/tar/project-x.x.x.tar

Which will install our project into our erlware directory, this will allow us to run our application from the bash shell:

erl -s project -s reloader

See few birds, one stone ;) , we have a way to manage, generate our docs, install them using Faxien & run our project from the bash shell.

The last step was simply a pain in the ass up until this afternoon, when I was playing around with BeepBeep, there is an erl application called reloader which helps to hot swap modules, that is what ‘-s reloader’ was in the above code example ;) , this had me for ages, without it applications need to be restarted, which is a pain & waste of a bloody good feature.

Still to work out

Well I’ve pretty much got the basic tools I need to develop confortably with Erlang, there a just a few more things left to work out:

  • TDD (mainly on applications & gen_servers
  • Automate the generation of docs & project build
  • Error logging/reporting

TDD
I still need to get my head around the TDD process within Erlang, thought conceptionally I think I have it down I have yet to implement it in any of my current projects, I saw some post earlier which I mailed to myself, hopefully I’ll have the chance to read over them again finally get back to my testing (feel naked without it).

Automate the generation of docs & project build
After a while it gets tiring running the same few commands over and over, at some point I really should find a way to integrate sinan/faxien into emacs, so I can can within emacs.

Error logging/handling

To be honest I’ve been kind of lazy with this, if you’ve noticed I’ve neglected to talk about sasl or anything like that, hopefully over the coming days I’ll have time to brush up on that & my Mochiweb/BeepBeep skills.

Finally

Well that yet another post finished, hopefully in the up and coming days I’ll have time to document using BeepBeep & integrating it into a Sinan application.

h1

Lighting the tunnErl Pt 4 – Erlang from a OOPer

January 6, 2009

Well this is a little deviation from the previous posts but I’ve ponder writing this post and held back until going back and working with PHP for the first time in a number of weeks.

I’ll focus purely on the productivity of Erlang vs C clones purely from an observation stand point and will leave code comparisons for another blog.

Productivity

To be honest from my perspective people are as productive as the knowledge and tools they have at their disposal (tried coding a web site in assembly or with buttons?). Initially learning any language or paradigm can appear to slow things down, I feel this is down to the fact the time is need to understand the basics (things that you already know how to do with other tools). At the same time if one is observant of the things that slow them down and work on improving their skills (or addopt new ones) in that area, they soon find their selves just as efficient in those area (sometimes more) as those areas you are traditionally more productive in.

PHP

I picked up the language a while after learning and not liking Perl for a web language (for the same reason you dont usea fork to eat soup). I’d been coding C/C++ for a while years prior so the transition was not an issue at all. Initially there wasn’t any decent libraries out there so I had to build things myself. Now 6/7 years later we have frameworks coming out the wood works and all I have to do really is do a little molding, today was a perfect example, being bored I remember I needed a exception handler. The mailer had already been built & for the logging I simple extended Zend_Log, after an 20 mins I had a basic exception handler and was off to the next task.

Now saying this I’m pro TDD and use tools to improve the way I work within PHP, as with most I use frameworks, test units & read a crap load, so naturally that helps.

Fence sitting

It has been said that Erlang lacks the tools to compete against PHP/Ruby & the such like, it certainly has a path to walk but  saying that it definitely has some decent tools & frameworks around as I’ve highlighted in past posts, which path the way for Erlang taking over some tasks we use PHP & Ruby for these days. There are already a few decent projects out there for the erlanger yaws, mochiweb, beepbeep, erlyweb, etap, not to forget faxien & sinan.

On the other side of the coin, most OOPers wont like the language and I’ve heard/read a few comment on how the syntax makes them feel uneasy, admittedly when I reflect back to the first time I saw Erlang syntax it threw me for six but honestly I thrive on change and quickly found myself wanting to know how the language worked.

Once delving in it was a trial of swings and round abouts, if it wasn’t down to the fact that I practically sleep with ‘Programming Erlang‘ & watch ‘Erlang in Practice‘ I would of given up past Erlang’s docs title page. The resources in my post helped me no bound, along with my stubborness to work things out I don’t think I would of held out to get my head around it. Oh and I forgot to mention, if you don’t know about faxien, then 9/10 one has to resign to compile source, which is all when and good up until upgrade or removal time :/.

Erlang

Well like i’ve said before I am no way near as proficient in Erlang as with PHP/C and its clones, simply down to the amount of time I have spent using it (4 months study, 3 1/2 practical). Having said that, there are a few things I have observed.

Things that were hard to do in C or PHP (created/manage multiple tasks) are pretty damn easy in Erlang implement a web server, 2mins… can’t do better than that in any other language I know, not even with apt-get. Saying that it works both ways, creating test cases/suites is not well documented leading to not testing and generally hacking, which is pretty crap in my eyes & the analyse tools could be abit more friendly (I’m still trying to get my head ronud dialyze).

The documentation for Erlang isn’t the best (I’ve yet to find decent TDD examples out in the wild on on Erlang & edocs takes some getting used to). Though the community is filling the void with alot of examples and articles, not to forget the community based sites (TrapExit, PlanetErlang, etc). The modules could be more concise and could be organised better but hell, I’ve seen all this before in PHP (remember pre OOP?) & C, they started of patchy and then become stronger as the community recognised them and bridge those gapst.

Erlang makes communication between nodes childs play, as I’ve mentioned in previous posts, a lot of my stumbling blocks with erl come down to over complicating things (an OOP trait). I think once I have gotten out of that habit with Erlang then my productivity increase that bit more. Spawning processes are made as simple as it could ever be & interacting with processes are just the same once you get over the pitfalls (from stores the pid & its ref, forgetting to catch a message, etc).

Things like creating servers is childs play also, making it easy to not only create a number of daemons but hotswap them as and when you feel.

Tools of the trade

Now I’m a firm believer in using the right tool for the right job (just because you just got a shiney new hammer, dont mean you would paint windows with it), the main reason I took up Erlang was because it seems like the right tool for scaleable, system & reliable systems.

Erlang does an excellent job and connecting with numerous nodes and spawning processes to deals with pieces of work. PHP does and goes a good job and helping to create dynamic websites (though to be honest this is a quickly changing trend) Ruby seems to be the bread winner at the moment whilst PHP tries to play catch up. C/C++ do except jobs of allowing us to work closely with assembly code & easily add assembly directly to its sources. Saying this it can take a good few days to get a C application to work ok with threading (barring all the checks & locks) not to mention the time taken to do the real work.

The one thing I love about Erlang is that it hasn’t shunned off the rest of the languages and makes it quite easy to manipulate data even if its at binary level (Joe Armstrongs Icecast example being and shining display of manipulating ID3 tags without the use of external libraries & the such like).

From my current perspective Erlang is excellent for prototyping systems and for creating those reliable highly configurable backend system, we all dream about, that said, it doesnt mean that you should use it for any & everything, sure tinker with it & having a play with the possiblity but hell taking Erlang on board and disregarding the rest would just be plan silly (imo its just something else to add to the mix). I generally don’t pick up things unless it has a practical use, interests me or I enjoy working with it. At the moment Erlang is all of that but Im still not going to push it on all my new projects.

Final words

In the last week or two I have become real comfortable with Erlang and have been working on another chat-engine (Chatterl) more and more, I’ve done a few in other languages mainly PHP & Perl, so once I have some of the functionality reflected in my older versions, I’ll dig out the most recent & do some code comparisons. For now I invite you to check out Chatterl’s source over the coming weeks I’ll be focusing on the web interface so I should be able to make some comparisons that that area also.

I’ll say this though, it took a day to whip up the base of my PHP chat system, with basic chat functionality. It took me a few more days to do the same with Erlang and create a system that can spawn groups & users over a number of nodes & shut down them nicely. Doing something like that with pure PHP is just not possible & in C++ a pain in the ass.

h1

Lighting up the tunnErl Pt. 3 – AftErl the basics

January 5, 2009

As promised this post follows on from the previous post, documenting my experience with Erlang over the past few months.

This one focuses on cock-ups and general mistakes I’ve made over the past few months, putting them here helps you to not make the same mistake & helps me to remember what to I did at that time, as I’ve said before killing a few birds with one stone is my thing.

AftErl the basics

By now I had decided to play around with Twitter’s API seeing as I use it a hell of a lot and web based applications are my thing (there is no better way to learn something that to use it). This provided me with quite a bit of insight when it came to developing in Erlang. I found these to be common over sights & issues:

  • Forgetting to end a line properly.
  • State weirdness.
  • Not catching a process message.
  • Spawning processes within processes.
  • Handling stopping child processes.
  • Module definition not the same as file name.
  • Creating result structures.
  • Parsing XML.
  • Working processes die once they are linked to a supervisor.

Forgetting to end a line properly

This was one of my most common mistakes, something that I still miss from time to time, the easiest thing to do is to remember the following:

  1. Each pattern match within a case ends with a semi-colon, unless its the last which is not terminated.
  2. If a case encapsulates multiple cases each end clause should finish with a semi-colon, with the last encapsulated case not being terminated.
  3. When refactoring a case, be sure to take note of the end of the case, moving the last case to the anywhere else means that that and the now last case needs to be refactored.

I assure you you will no doubt get into this issue as a newbie, as I’ve read it is one of the few issues others have with it as beginners. As long as you remember those points and if really stuck check against a piece of code that you know works & you should be fine, just a couple of examples taken from a system I am working on at the moment:

case gb_trees:is_defined(User, State#foobarz.users) of
    false->
        io:format("~p connected to ~p~n", [User,?MODULE]),
        {{ok, "connected"},
          gb_trees:insert(User, {User,From}, State#foobarz.users)};
    true -> {{error, "Unable to connect."},
                       State#foobarz.users}
end.

This is an example of a basic case clause, as we don’t want to process the results, we simply terminate with a full stop. to Tell Erlang to return case’s results.

determine_user_action(GroupName,{Action,PayLoad},UsersList) ->
    case Action of
        drop_group ->
            GroupMsg = "Sending disconnect message to ~s~n",
            send_msg_to_users({drop_group,GroupName},UsersList,GroupMsg);
        receive_msg ->
            case PayLoad of
               {CreatedOn,Sender,Message} ->
                   GroupMsg = "Sending to users ~s~n",
                   send_msg_to_users({receive_msg, CreatedOn,Sender,Message},UsersList,GroupMsg);
               _ ->
                  {error, "Illegal payload format"}
            end;
        _ -> {error, "Illegal action!"}
    end.

This method is a little more involve and displays and example of a case encapsulated method, first we do the basic pattern matching, if we get the atom recieve_msg we want to use another case to check that the payload is what we expect it to be, you main thing to notice here is that the inner case statement terminates with a semi-colon which tells Erlang that this is the end of the expression.

Not catching a process message.

This is another common mistake on my behalf, either passing the wrong pattern or forgetting a trap_exit, this is something to watch out for. to save a lot of unnecessary system crashes, I’d suggest testing out pattern matches via a separate virtual node, allowing you to determine the best patterns for the task. If the process is supervised make sure that you use process_monitor(trap_exit, true) with the init of the gen_server.

State weirdness

Remember when using gb_trees:insert and the such like the new data is returned as the result & not updated internally, it is very easy to forget this, especially coming from an OOP background. So if you notice that your state is not being updated, check that the result of such methods is being passed and not left in the ether.

Another similar issue I have recently come across is mangled states within gen_server, I was basically trying to update a state if something changed, though instead of return the state property if the was no update I passed the whole state, leading in warped data, this can be quite serious & very hard to find. Here is the culprit:

handle_call({disconnect, User}, _From, State) ->
    {Reply,NewTree} =
        case gb_trees:is_defined(User, State#foobarz.users) of
            true ->
                {{ok, "User dropped"},
                 gb_trees:delete(User, State#foobarz.users)};
            false ->
                 {{error, "Unable to drop group."},
                  State}
        end,
{reply, Reply, State#foobarz{ users = NewTree }};

Well it seems safe enough right?, after noticing a bug in part of my system and realising that the state looked stranged, it wasn’t until I took a step back that I noticed the actual bug & to my amazement the bug was present in a couple of methods (I hate copy & paste). To be honest this to date is probably one of my biggest cock-ups & potentially one of the damaging bugs I’ve introduced into a system in a long time, I’d hate to see how many other system have fallen prey to this oversight.

Just so that there is an example out there for future reference here is the corrected version of the above code.

handle_call({disconnect, User}, _From, State) ->
{Reply,NewTree} =
case gb_trees:is_defined(User, State#foobarz.users) of
true ->
{{ok, "User dropped"},
gb_trees:delete(User, State#foobarz.users)};
false ->
{{error, "Unable to drop group."},
State#foobarz.users}
end,
{reply, Reply, State#foobarz{ users = NewTree }};

Spawning processes within processes

I was stuck on this for a few days and still think there is a better way I about this, spawning a new process is so simple it didnt occur to me that when creating a gen_server the gen_server was actually spawning a new process (duh, read the source). I subconciously took this in whilst reading up on it but when it came down to doing it myself it had me stumped, here is what I was trying to do:

spawn_link(mod_gen_server,start_link,arg).

The process I was trying to spawn was a gen_server and already spawning a process within itself, so what I was effectively trying do was spawn_link something that was trying to spawn a another seperate process, not quite what I wanted & Erlang definately didn’t like it, all I needed was to call the process and to link/monitor it. That simple.

Multiple processes

Well this was another one, once I worked out how to link a process I soon realised I needed that child process to have a unique module name, this is another one that may seem hard but in practicality it is yet again very simple.

start(Name,Desc) ->
    gen_server:start_link({global, Name}, ?MODULE, start, [Name,Desc]).

This way, the process is given the name passed the user, there are probably safer secure ways of doing this but for what I need at the moment, it works at treat.

Module definition not the same as file name

Is such a basic thing to oversee especially coming from a language where file names aren’t so important, its a simple one to fix but yet a common gotcha. Emacs has a nice lil feature that which basics alerts you to this fact and asks you if you want to changed it.

Creating result structures

Yet again another simple practice but if you come from a purely OO/C based language environment & just finished working on a OO based project or something, watch out for this, getting used to it takes some time. Simple rule:

  • Manipulate Term, giving unique names to needed terms
  • Store resulting terms into new pattern

Lists can simply be manipulated by postfixing a new list element to an existing on:

{{FName,_MName,LName},Address,Number,_OtherStuff} = UserDetails,
[[FName,SName,Address,Number]|Results].

Parsing XML

Whilst messing around with my Twitterl project, I quickly realised one thing, how was I to parse XML (second nature to me in PHP/C++) in Erlang though it did take me a while to get my head around, thanks to some related code by Nick Gerakines, reading his code definately shed some light on the area.

This is still a doozy, hopefully I’ll find a better way of doing this, basically we use xmerl_xpath:string/2 to retrieve an XML element, this result is a tuple, so we need to work on it further to retrieve the actual value, this could simply be done by:

[#xmlText{value = Value}] = xmerl_xpath:string(XML, "/item/title/text()").

I had implemented a variation of this code within my module but found it slow, so after reading a comment from Nick Gerakine’s in relation to my project, I had a look at his code for his Twitter API & noticed a bit of code that did they type of functionality I wanted, I’d like to find a way to improve this some more, mainly by looping over a record (still to learn) but it definately does the trick & imspires me to write more elegant code:

parse_item(Node) ->
    Item = #tweet {
      title = format_text(Node, ["/item/title/text()"],""),
      pubDate = format_text(Node, ["/item/pubDate/text()"],""),
      link = format_text(Node, ["/item/link/text()"], "")
    },
    Item.

This method also takes two Terms, the XML node & a list of XPath strings, it passes the node off to format_text, which does most of the work:

format_text(_, [], Result) -> Result;
format_text(Xml, [Xpath | Tail], Result) ->
    Results = lists:foldr(
        fun(#xmlText{value = Value}, Acc) ->
            lists:append(Value, Acc);
        (_, Acc) -> Acc
        end,
        Result,
        xmerl_xpath:string(Xpath, Xml)
    ),
    format_text(Xml, Tail, Results).

Here we basically loop over the XPath list retrieving the results and storing them in a list called Results, when the list of XPaths is empty we return the result, as most of the time I only need the one XPath it this method wasn’t introduced until i needed to play around with Twitters Users & Statuses XML.

Well that generally covers it, there is still a few more things a I want to cover & no doubt I’ll add more to this post as

Stuff I have yet to learn

  • Still not got round to getting getting auto-complete work under emacs.
  • Error and log handling principles, how to recover from a termination.
  • erl_crash.dump, is totally alien to me.
  • RESTful applications (have done some R&D but have yet to implement the actual functionality).
  • TDD & the whole process is still not well documented, ideally I want to be able to develop using the same TDD process I use in OOP.
  • Find out how to inplement a continous integration system to make development smoother.

Admittedly alot of this is more best practices and handling production code but I’m never happy until I have these things ironed out ;) .

Well its been near four months since I started coding Erlang & I’ve got to say I’m enjoying the hell out of it, I thought the curve would be steep & admittedly initially it was, I still have moments of total confusion but I’m sure the more I play with Erlang the less this will happen, hell I still have those moments in C & PHP so nothing really different there.

Next

The next post will focus on how to put all this together to make an OTP system & how to main builds using Erlware’s Faxien & Sinan.

h1

Lighting up the tunnErl Pt 2 – Discovering a new wErld

January 5, 2009

This post continues on from Part 1, this post focuses primarily with the concepts of Erlang, throwing in a few tips as I go along.

The Basics

There are heaps of places to pick up the basics as mentioned before (Erlang, TrapExit, PlanetErlang & Lighting up the tunnErl Part 1 are good starts) but I’ll highlight some functional fundermentals to help understand the basics of Erlang code.

Term definitions

  • Atoms – depicted by a lower case string some_atom
  • Tuples – depicted as {Term}, can have a number of atoms, tuples & lists.
  • Lists – depicted as ["a","list"]
  • Term (a mixture of the above).{a_simple_atom,Term,["a","list"]}

A few tips

Well things are as easy as you make them, so here are some tips that may help whilst programming with Erlang.

  • Terms are pretty much immutable (though state & records can be changed).
  • Make sure that Terms that are different have different names, coming from OOP it is all too easy to over look the fact that two actual Terms can not share the same name. The following will cause an error
    Term = 'hello". Term = {term}.

    & even harder to debug

    Term = 4. Term = 2 + 2.

    just means that 4 is identical to 2+2.

  • If you change a match pattern, make sure all references of it are refactored.
  • Terms that you’re not bothered with should start with a ‘_’ ie. _DontWant, could just use _ but when coming back to the code, it makes it harder to understand.
  • Start off small, get familiar with erl & passing around Terms.
  • Test out the modules & commands your not familiar with in erl, it will save you time when it comes to actual coding.
  • Have a browse of other Erlang projects, read through the source, see what modules are commonly used & how things are done.
  • Get used to the Erlang documentation & the commonly used methods (lists,ets.dets.gb_trees).
  • OOP natives beware: the sooner you get used to using the word ‘term’ instead of ‘variable’, when thinking in Erlang, the quicker the transition.

A few examples

Now I’m not going to go into great detail here, though I will show some basic examples of the various terms, I wont go into details as usual, I’ll leave that for you guys to read up on if you already don’t know, curiously is king:

a_simple_atom
ATerm
{a_simple_atom,ATerm}
{}
{{ATerm,[SumList]},_DontWantThis}
[]
["foo","bar"]
Term = {{{ATerm,[SumList]},_DontWantThis},["foo","bar"]}

Are funs fun?

It didn’t take long to get to grips with the basics, understanding funs was a different ball game though. I think it comes down to the same issue I initially had with XML, it is so flexible you don’t quite know where to start with it, so here’s something I use in one of my projects:

    lists:foreach(
      fun(GroupName) ->
      io:format("Dropping group ~s...~n",[GroupName]),
      gen_server:call({global,GroupName},stop,infinity)
      end,
      GroupNames).

Here the following steps are taken:

  1. Loop over each of the GroupNames them (using method lists:foreach)
  2. Each result is stored and passed as the term Groupname
  3. Prints a message using GroupName for a dynamic value.
  4. A call is made to the process to shutdown.

Steps 2 & 3 are where the fun begins (pardon the pun), we tell it to take an argument (GroupName) & then to execute everything within the fun, this is an extremely powerful feature, one which I still have yet to manipulate properly. I’d suggest messing around with them abit (using others code) and getting used to their power and flexiblity, you’ll soon find funs are fun.

That does it for this post, the next will focus on after the basic, hopefully giving you a chance to delve into the fundermentals of Erlang.

Next
I will focus on the actual problems & issues I’ve faces whilst working with Erlang, this can be found here.

h1

Lighting up the tunnErl Pt 1.

January 4, 2009

Well after a few months of playing around with Erlang, I thought I’d put my findings in one place for myself and others.

Well for those that aren’t familiar with Erlang or never heard of it, in a nut shell Erlang is a functional programming language create multiple processes across multiple nodes, allowing for a reliable & fault tolerant system.

It allows us as developers to develop applications over a number of nodes, these nodes can be either local to the machine they are running on or on a totally different machine running the same software, this allows for concurrent reliable systems.

I wont go into too much detail on how all this works because it’s done so well in other places (Erlang).

This post will cover the learning resources I’ve found useful & invaluable to my exploration into Erlang, the 2nd will highlight mistakes & general cock-ups made over the past few months. Followed by the 3rd, dealing with project management and how we can achieve this & more with Faxien & Sinan.

There is a decent number of sources out there for Erlang from code examples to general tutorials & articles a few of them which you can find at the bottom of this post. Not to mention a hell of alot of useful and interesting projects created with Erlang (CouchDB, ErlyWeb, Mochiweb to name a few).

Myself I’m focusing on using Mochiweb, Beepbeep & CouchDB for web applications. Mochiweb to deal with RESTful requests/responses, Beepbeep to deal with the MVC  of the application & CouchDB to store data (documents). If you haven’t already read up on CouchDB I suggest you do, it may well give you some nice ideas ;) .

Well I as mentioned in a previous post I’ve had the itch to learn a new language. I started off by reading Programming Erlang by Joe Armstrong (a must have for anyone making the jump into the world of Erl. It has helped me no end when my brain goes blank & I’ve forgotten how something in Erlang works. Over the months I’ve practically slept with my copy, the examples are elegant and Joe has an excellent job of creating a good introduction to Erlang and its practices.

That is where ‘Erlang In Practice‘ (Screencasts by Kevin Smith) this set of screencasts are definately worth the £20 odd I spent on it. The most useful being episode 6 & 8 which focus on e-unit & supervisors respectively. Though admittedly the episode on e-unit could of focused a bit more on testing OTP based modules (I guess I’ll have to pick this up later).

Still there is more to learn, personally the best way to learn something is to do it, so I’ve played around with the shell whilst working through examples, got myself familar with the OTP documentation and stifted the net for code examples, githubs a nice place to look (ngerakines, davebryson & few others have some decent code you can get some ideas/insipration from)

Resources
There are alot of new tools coming out and it is always interesting to see what others are doing, heres some sites/blogs that I find myself practically attached to:

Well I think that pretty much wraps it up for part 1, part 2 is in the drafts so it should be published in the near future. If you have come across any other useful resource, feel free to drop me a comment, the more information the better imo ;)

h1

Chatterl – Erlang based chat engine

January 1, 2009

Well I’ve been hacking around for the past few months trying to get my head around Erlang. After playing around with Twitterl I decided I should start a new project (OTP based) which I have a decent understanding of & have wanted to work on for some time. A chat system was the first thing that came to mind, I’ve worked on and built a few in my time and thought Erlang would be a good language to build a chat engine from scratch.

For those not interested in the long description and prefer to dive in source, you can find a copy of the project at github.

Description

A chat system that can be housed over a number of nodes and track clients over varying devices, at the time of the writing the system works over multiple nodes and is able to do the basics (connect to a group, send message to other clients and connected groups).

The main focus of this project is to create a chat system that is highly reliable as well as scaleable. Other developers will be able to create add-on modules that are able to interact with chatterl and further enhance the functionality of chatterl and the chatterl clients experience.

As mentioned the system is OTP based, of which it uses Sinan to maintain its builds.

Installing Chatterl

At the moment of this writing Chatterl is still in alpha so their is no real release at the moment, to get it running you will need to do the following:

git-clone git://github.com/baphled/chatterl.git &&
cd chatterl &&
sinan doc && 
sinan dist &&
cd _/build/development/tar &&
sudo faxien install-release chatterl-0.1.0.2.tar.gz

The above presumes that you have Sinan configured & installed, if you haven’t refer to erlware.
You will need to change to cookie & name values to something else, doing so should drop you into the erlang shell & ready to run the Chatterl application. To run a client on a different machine you will need to do the above if (making sure that the -sname is not the same as any other connected nodes & that the cookie is the same) if connecting on the same box simply cd to the ebin directory and run the following command:

erl -name bar -setcookie abc

From here you will need to make sure that they nodes can connect via:

net_adm:ping(foo@bar.net).

Where foo is the node name & bar.net is the tld of the node box (indicated within yout hosts file or dns server).
Once you receive the infamous pong response you are ready to roll.

Features

  • Client login/logout to Chatterl.
  • List Chatterl groups.
  • List Chatterl users.
  • Login/logout of a chatterl group.
  • Send message to a group and other clients.

Future Features

  • Centralised Error logging and data storage.
  • Client customisable routines (able to poll RSS feeds, twitter, FB and the such like).
  • Better handling of errors.
  • User registration.
  • FB Connect.
  • Chat bots (AIML based).
  • Web interface/API.
  • Chat modules handler(banning, censorship, chatbots).

Useage

Starting the server
Chatterl server runs as an OTP application and uses a supervisor to manage it (in later versions there will be options to spawn multiple servers, allowing for a more fault tolerant chat system). To start up the server you simply need to run the following command:

application:start(chatterl).

Which will initialise the server allowing clients to connect and groups to be created. Groups can be created on differing nodes as long as the node can communicate with the chatterl_serv.

Starting a group
Chatterl groups can be started on any node that can communicate with the server, this allows the user to create a number of groups on varying nodes, helping with general organisation as well a performance and reliablity.

A group can be initialised by calling the command:

chatterl_serv:create("room","description").

which will spawn a group process which users can connect to.

Connection to chatterl
At the time of this writing chatterl_clients can only spawn a client per node, this will later be changed once the web interface has been fully implemented, possibly to a refactoring the client to a parameterised module.
For the moment node users must follow the basic OTP configurations (same cookie, valid DNS name, etc). Creating a connection to the server is done by using the following command.

chatter_client:start(UserName).

This will initialise a user and connect them to chatterl_serv (must be done before users can join a group or communicate with other chatterl users).

Disconnecting from chatterl
Chatterl clients can simply disconnect from chatterl by issuing the following command:

chatterl_client:stop().

This will disconnect the user from all the groups they are currently connected to as well as the actual Chatterl server.

Joining a group
This can be done by using the following command:

chatterl_client:join(GroupName).

If the group exists the user is able to join the group allowing them to send message to the room.

Dropping from a group
This is as simple as connection, simply supply the following command:

chatterl_client:drop(GroupName).

This will send a message to the group, which will handle the termination.

Sending group message

chatterl_client:send_msg(GroupName,Message).

GroupName being the name of the group the client is connected to, Message being the message that you want to send to the receiving client. If the message is sent successfully all users connected to the group will receive the message.

Sending a private message
This allows a Chatterl client to send a private message to another client, by executing the following:

chatterl_client:private_msg(RecipientName,Message).

If the message is sent successfully then the sender will receive follow message:

{ok,msg_sent}

in turn sending the message to the receipients node.

h1

Creating a Twitter client in Erlang

December 1, 2008

So I’ve been playing around with Erlang for a little while now and decided to create a small client for one of my favourite mini blogging services (Twitter), which I’ve decided to share with all, both to help other noobs and for myself a personal reference.

So we want to be able to retrieve a REST like response from twitter, where do we start? First thing was to start up erl from the command lineerl -pa ~/erlware/packages/5.6.3/lib/*/ebin "$@"

I had installed erlware to my local directory & linked it into erl by running the above command. Now that we are in erl, I started inetsinets:start().

Now we are ready to start playing with http:response, I want to be able to retrieve the HTTP body response and do some XML parsing with it http:request("http://twitter.com/statuses/public_timeline.rss")
which returned me something simular to
{ok,{{"HTTP/1.1",200,"OK"},
[{"cache-control","max-age=1800"},
{"connection","close"},
{"date","Mon, 01 Dec 2008 10:46:06 GMT"},
{"server","hi"},
{"content-encoding","UTF-8"},
{"content-length","9251"},
{"content-type","application/xml"},
{"expires","Mon, 01 Dec 2008 11:16:07 GMT"},
{"set-cookie",
"JSESSIONID=2C9CFD77A4EF365B46884168D089FD4A; Path=/"}],
[60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,
46,48,34,32,101,110,99,111|...]}}

With a little digging, we come to find out that the following pattern matches pretty nicely{ok,{_Status,_Head,Body}} = http:request("http://twitter.com/statuses/public_timeline.rss")
Typing Body. in the erlang shell returns a list simular to the following:[60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,
46,48,34,32,101,110,99,111,100,105,110,103,61|...]

Now this is our HTTP body response, now we can fire up emacs or your favourite text editor and create our first method. -modules(twitterl).
-compile(export_all).

retrieve_response(Url) ->
{ok,{_Status,_Head,Body}} = http:request(Url),
Body.

Make sure you save this file with the same name as the module (or Erlang will complain) & make sure the file is in the same directory that erl is running in. c(twitterl).
Will compile our piece of code. Now we should have the following command availabletwitterl:retrieve_response("http://twitter.com/statuses/public_timeline.rss").
Which will give u the same result as the previous commands passed to erl. Now the Body term still has our HTTP body so well play with this for the time being, if not then just do the following:Body = twitterl:retrieve_response("http://twitter.com/statuses/public_timeline.rss").
Now for the next piece, we actualy want to parse this body and retrieve all its descriptions (which stores our actual twitters).xmerl_scan:string(Body) Give us a result simular to the following:xmerl_scan:string(Body).
{{xmlElement,rss,rss,[],
{xmlNamespace,[],[]},
[],1,
[{xmlAttribute,version,[],[],[],[],1,[],"2.0",false}],
[{xmlText,[{rss,1}],1,[],"\n ",text},
{xmlElement,channel,channel,[],
{xmlNamespace,[],[]},
[{rss,1}],
2,[],
[{xmlText,[{channel,2},{rss,1}],1,[],"\n ",text},
{xmlElement,title,title,[],{xmlNamespace,...},[...],...},
{xmlText,[{channel,2},{rss,...}],3,[],[...],...},
{xmlElement,link,link,[],...},
{xmlText,[{...}|...],5,...},
{xmlElement,description,...},
{xmlText,...},
{...}|...],
[],"/home/baphled/projects/erlang/status_managerl",
undeclared},
{xmlText,[{rss,1}],3,[],"\n ",text}],
[],"/home/baphled/projects/erlang/status_managerl",
undeclared},
[]}
This returns our XML and the rest of the HTTP body, we only want the XML so{Xml, _Rest} = xmerl_scan:string(Body) Will store our XML within the Xml term. Now we have the data we want to parse, we can use the following command to retrieve a list of tuples, containing our descriptions in XML format simular to the following.[{xmlText,[{description,4},{item,12},{channel,2},{rss,1}],
1,[],
[101,120,116,101,101,110,114,101,99,101,110,116,58,32,224,
184,161,224,184,178,224,185,129|...],
text},
{xmlText,[{description,4},{item,13},{channel,2},{rss,1}],
1,[],
"ston3monk: wild place where everyday brings somethnig new ",
text},
{xmlText,[{description,4},{item,13},{channel,2},{rss,1}],
2,[],
"& unepected. do i continue on the unknown, or do i go hang out on koh samui ",
text},
{xmlText,[{description,4},{item,13},{channel,2},{rss,1}],
3,[],"& work 4 a while?",text},
{xmlText,[{description,4},{item,14},{channel,2},{rss,1}],
1,[],
"juffrouwjannie: @Hoof is het al latenweoveralweerzoutopgaanleggendag?",
text},
{xmlText,[{description,4},{item,15},{channel,2},{rss,1}],
1,[],
[116,104,97,105,50,104,97,110,100,58,32,91,84,50,72,93,32,
224|...],
text},
{xmlText,[{description,4},{item,16},{channel,2},{rss,1}],
1,[],
[65,111,121,97,89,117,121,58,32,227,129,138,232,143,147,229,
173|...],
text},
{xmlText,[{description,4},{item,17},{channel,2},{rss,1}],
1,[],
[101,99,108,117,99,105,102,101,114,58,32,64,105,99,104,105|...],
text},
{xmlText,[{description,4},{item,18},{channel,2},{rss,1}],
1,[],
"simonandre: @fabienthomas envoie leur un mail ils sont super r\303\251actifs.. je l'avais fait y'a un an, dans les 48h \303\247a avait \303\251t\303\251 corrig\303\251",
text},
{xmlText,[{description,4},{item,19},{channel,2},{rss,1}],
1,[],
"debugz: @draconiams I saw some male chicks from here today,they are hott too =P",
text},
{xmlText,[{description,4},{item,20},{channel,2},{rss,1}],
1,[],
"csinctw1: [JCSAGE] About to build project=mobility status=Success",
text},
{xmlText,[{description,4},{item,21},{channel,2},{rss,1}],
1,[],
[101,108,101,99,116,114,105,99,97,108,80,101|...],
text},
{xmlText,[{description,4},{item,22},{channel,2},{rss,1}],
1,[],
[108,117,110,97,114,121,117,101,58,32,231|...],
text},
{xmlText,[{description,4},{item,23},{channel,2},{rss,1}],
1,[],
[109,49,48,56,58,32,230,172,161,227|...],
text},
{xmlText,[{description,4},{item,24},{channel,2},{rss,1}],
1,[],"DerAlbert: @adventskalender open 1",text},
{xmlText,[{description,4},{item,25},{channel,2},{rss,1}],
1,[],
[100,97,105,95,97,105,114,58|...],
text},
{xmlText,[{description,4},{item,26},{channel,2},{rss,1}],
1,[],
"backfunshop: backfunshop.de : backfun.de ** Bratentopf 28cm 6,7l auch f\303\274uktionsherde http://tinyurl.com/69ezcc",
text},
{xmlText,[{description,4},{item,27},{channel,2},{rss,1}],
1,[],
"drillhalllib: Want the chance to win \302\243100 in Amazon vouchers? Take part in this years Student Satisfaction Survey now! http://moourl.com/dhl08",
text},
{xmlText,[{description,4},{item,28},{channel,2},{rss,1}],
1,[],
"techdigest: Considering moving to a Dvorak keyboard - anyone ever tried it? http://tinyurl.com/9x84j",
text},
{xmlText,[{description,4},{item,29},{channel,2},{rss,1}],
1,[],
"franksting: @stilgherrian huh, whats that about throat infections? Both ms3 (i can say that now) and I have something and we both went swimming on S ...",
text},
{xmlText,[{description,4},{item,30},{channel,2},{rss,1}],
1,[],
[65,108,108|...],
text},
{xmlText,[{description,4},{item,31},{channel,2},{rss,...}],
1,[],
"abcnewsVic: Great Ocean Road reopens after fatal smash: A stretch of the Great Ocean Road that was the scene of a .. http://is.gd/9HAP",
text}]

Now we go back to our source file and create a method for our discovery:latest_twitters() ->
Body = retrieve_response(?PubTimeUrl),
{Xml, _Rest} = xmerl_scan:string(Body),
Twitters = xmerl_xpath:string("//item/description/text()", Xml),
Twitters.

This method will use our previously created method to retrieve our response and then we parse XML searching for the description element within the item element, this then stores each of the enteries in Twitters, which is then returned. Save and recompile the file. We can now use our latest_twitters method to returl a list of our results.Twitters = twitterl:latest_twitters() will store our list to our Twitters term. Now we now we have a list so we will manipulate it as follows to see how we can deal with our results.[H|T] = Twitters. gives us the first term in the list, something simular to the following:{xmlText,[{description,4},{item,12},{channel,2},{rss,1}],
1,[],
[107,105,114,105,108,108,95,121,117,114,105,58,32,228,187,
138,229,185,180,227,129,174,231,180|...],
text}

Lets break this down a little so we can deal with the specific data we are interested in, now our term is a tuple containing an atom, a tuple,another atom,an empty list, followed by our text, proceeded by an atom. We only need the text string so the following pattern will do us.{_,_,_,_,Title,_}Lets give it a try.{_,_,_,_,Title,_} = H.
io:format(Title).
We get a result simular to:kirill_yuri: \344\273\212\345\271\264\343\201\256\347\264\205\347\231\275\343\201\257\347\264\205\343\202\222\345\213\235\343\201\237\343\201\233\343\201\237\343\201\204\351\233\260\345\233\262\346\260\227\343\201\214\345\205\205\346\272\200\343\201\227\343\201\246\343\202\213\346\260\227\343\201\214\343\201\231\343\202\213\343\202\223\343\201\240\343\201\214\343\201\251\343\201\206\343\201\213\343\201\255\343\200\202 The above is our actual twitter, now armed with this piece of information & a little tinkering we can add another method to our source file.loop_twitters([Twit|Twitters]) ->
case is_tuple(Twit) of
true ->
{_,_,_,_,Title,_} = Twit,
io:format("~s~n",[[Title]]),
loop_twitters(lists:reverse(Twitters));
false ->
{error, "Unable to read twitter"}
end;
loop_twitters([]) ->
ok
We’ll need to do a little refactoring to make everything play nice. Namely refactor our latest_twitters method to pass our twitters on to loop twitters. I guess we’ll want to only export one method now also, which in this case will only be the latest_twitters method. This is done by removing the line-compile(export_all). and replacing it with-export([latest_twitters/0]).

Our source file should look like this:
-module(status_managerl).
-compile(export_all).
-export([init/0,stop/0,latest_twitters/0]).
-include_lib("xmerl/include/xmerl.hrl").
-define(PubTimeUrl, "http://twitter.com/statuses/public_timeline.rss").

init() ->
inets:start().

stop() ->
inets:stop().

retrieve_response(Url) ->
{ok,{_Status,_Head,Body}} = http:request(Url),
Body.

latest_twitters() ->
Body = retrieve_response(?PubTimeUrl),
{Xml, _Rest} = xmerl_scan:string(Body),
Twitters = xmerl_xpath:string("//item/description/text()", Xml),
loop_twitters(Twitters).

loop_twitters([Twit|Twitters]) ->
case is_tuple(Twit) of
true ->
{_,_,_,_,Title,_} = Twit,
io:format("~s~n",[[Title]]),
loop_twitters(lists:reverse(Twitters));
false ->
{error, "Unable to read twitter"}
end;
loop_twitters([]) ->
ok.

Now finally we'll compile our source file and run using the following commandsc(twitterl).
twitterl:latest_twitters()

Will produce our list of latest twitters simular to the following:timetoleadfr: @otromundo merci d'avoir relay\303\251 le message :)
bernardoruas: @rejaneayres I hope so.
osa03: \343\202\246\343\203\274\343\200\202\343\203\255\343\202\270\343\203\203\343\202\257\343\201\214\343\203\257\343\202\253\343\203\203\343\202\277\343\203\274\343\200\202
olemi: @DavidFeng: \345\260\215\344\270\215\350\265\267\357\274\214\346\210\221\344\270\215\347\237\245\351\201\223Catch-22\346\230\257\347\224\232\351\272\274\346\204\217\346\200\235.... :P \350\203\275\350\267\237\346\210\221\350\247\243\351\207\213\344\270\200\344\270\213\345\227\216\357\274\237 :)
ijournal: RenRe's WeatherPredict Acquires Assets of Commodity Hedgers http://twurl.nl/pa5urw
sydsvenskan: Man knivr\303\245nad i Malm\303\266:
En man blev under knivhot r\303\245nad strax efter klockan elva i en g\303\245ngtunnel vid .. http://tinyurl.com/6zktzc
prensa: NOUVELOBS: Venise : la mont\303\251e des eaux atteint 1,56 m\303\250tre: La mer commence
à se retirer l.. http://tinyurl.com/5nb6dd
Erik_Visser: Blijft toch een leuk verhaal van die belgische minister op het blog van Nathalie Lubbebakker. http://www.nathalielubbebakker.com/
petulak: @punio miedo me dais, cinematograficamente hablando!!
...

Well that's it for the moment, the code is far from perfect & i'll already started to refactor the code to do more, currently, Im able to search for a user, retrieve their latest tweets (from & to) as well as query terms used ie. #Erlang. Hopefully when I get the time I'll post some code to help others do simular things.

h1

Learning a new Er lang…

November 30, 2008

I’ve had the itch to learn a different language for a good while now, I thought about picking up Ruby or Python & saw no personal practical use for them, plus the fact that I’d still be stuck in the same paradigm just with different a syntax.

Whilst surfing a three weeks ago I came across a piece of code of which I had never encountered (I can’t recall where I stumpled upon this right now).

Being naturally curious my fingers sent me to Google, quickly followed by Amazon, the day after I had Joe Armstong’s “Erlang Programming” book. I have to say I cant remember the last time reading a techie book threw me into boughts of laughter chapter after chapter, not because it a helarious book but purely down to how the language solved problems.

list([Item|Items]) -> io:format("~p~n", [Item]), list(Items);
list([]) -> [].

As apposed to a ‘C type language’ which would look like:-

foeach($items as $item) {
print($item ."\n");
}

I’ve been playing with Erlang for three weeks now and am impressed, at the moment I’m playing with a twitter API, basically retrieving public & user specific twitters. Once I get my head around HTTP authentication with Erlang i’ll extend it further utilising a few other systems tying them together to track and send messages over multiple networks.

For now I’ll show you a little bit of code that will store the body of a HTTP response:
{ok,{_Status,_Head,Body}} = http:request("http://www.google.co.uk").

Firstly this is a piece of pattern matching one of the main princples of Erlang, on the right we retrieve a Tuple which we match to the left hand pattern, if the pattern is matched the response body is stored in Body.The pattern reads as:

“Our http:request from Google must match a Tuple containing the atom ‘ok’ preceeded by a Tuple containing 2 items we don’t care (_Status,_Head) and 1 which we’ll store in the item body.”

The other items (Status,_Head) are dismissed indicated by the prefixed underscore, removing the prefix would mead Status & Head would also be assign values.

It’s this pattern matching that makes Erlang fun to play with, you can quite easily find yourself getting losting in tuples, lists & atoms, at the moment I tend to find myself playing around with matching patterns within erl (Erlangs shell) storing the needed values.

In my opinion reading Joe Armstrong’s “Software for a Concurrent World” is a must, I’m still going through it now & find the reference in the appendix an constant help, I also found Kevin Smith’s screencast’s “Erlang in practice” an excellent help too, especially in regards to the TDD using eunit, I still have a great deal to learn in regards to TDD with Erlang, mainly down to me hacking around & trying to get my self familiar with the syntax.

There are also a number of cool tool, some of which I have yet to play with, mnesia (Erlang DBMS) is definately on my to play with list, along with Yaws (erlang based webserver) & Erlyweb (web ramework).

h1

Why test anyway?

October 27, 2008

Before I start I’d like to point out that this is purely from my perspective and pretty much a subjective point of view. There are so many articles out there from an objective stand point, that I thought I do this from my own, seeing as personal accounts are pretty much one sided & usually only highlight the good points. Here, though I’m obviously a TDD advocate I will try to address the issues I have come across whilst working with the methodology.

I know I’m not the only one who hates spending hours trying to track a bug & have phrases like: “where did that bug come from?” and “i didn’t change that” swish around my brain.

Over the years I’ve learnt that there is no such thing as a perfect solution but have adopted TDD purely because I have always felt that software projects lacked the flexibility of car designers (who test our concepts before making a final decision). Being security conscious and taking pride in my work I thought it would be of benefit to explore the practice first hand.

I’ve always hated pros & cons, especially as some peoples pros are others cons, so I’ll just bullet each methodologies attributes that I am aware of, make of it what you will.

No tests

  • Quick to initially code.
  • No need for test suite.
  • Cab be hard to trace errors & debug.
  • Can leads to misconceptions in design.
  • Changes could break existing code, without knowing and/or introducing new bugs.
  • Developers feel uneasy making changes to the system.
  • Debugging gets left to last or even out entirely due to time restraints.
  • Functionality can get left out or reproduced.

Tests

  • Need a test suite at hand.
  • Able to test each module as its built.
  • Easy to created dependencies within test cases.
  • Ideas can be played with without actually implement production code.
  • Need to adopt a different way of approaching problems.
  • Easy to track when the application is deliverable.
  • Errors/bugs can be picked up quicker.
  • There is always something to test.
  • Easy to recreate rare scenario’s/exception.
  • Can take time to learn how to create useful tests.

With those points out of the way, I’ll explain my reasons for taking the testing route.

Though software development is maturing at a pace we still have an urgent need to track change & check our assumptions. The quicker we can check our assumptions are correct the quicker we’ll find bugs in our software, I’m the first to admit I get bored quick, when my attention wains so does the software I’m coding, whilst testing I find that I become more productive & my focus is more on problem at hand, rather than tracking errors or debugging as most of the errors are expected and handled quickly.

Below is a list of my loves & hates in regards to the testing process, like I mentioned earlier I don’t believe in perfect solutions so I think it prudent not to gloss over the fact that just because something is tested doesn’t mean it does what it is supposed to or that a project will end up better.

Loves

  • Sped up my understanding of the problem at hand.
  • Alerted me to error I’ve over seen.
  • Easy to replicate hard to detect errors & exceptions.
  • Allows me to test ideas before implementing them.
  • Very handy when doing exploratory development (not sure how something works).

Hates

  • Creating useful tests can take time to learn.
  • Just because a test passes, doesn’t mean it is bug free.
  • Is easy to create useless tests.
  • If not careful planned, can find yourself testing more than creating production code.

From personal experience I found that once I grasped the concepts of testing (more so the TDD process, which I’ll go over in later blogs), the quicker I was able to implement functional code, whilst allowing me to test out assumptions I may have had. This along with a few other techniques (mainly design patterns & refactoring) has evolved my programming allowing me to create flexible, reusable code which I end up using in a range of projects.

Follow

Get every new post delivered to your Inbox.