A while back I wrote some code in Erlang to grab your public Amazon wishlist based off of your email address. Today I had the urge to rewrite it using OTP, specifically gen_server. The code is up on github. Switching it over to use gen_server is fairly trivial since the sequential code is already written. Basically all that needs to be done is to setup the handle_call method to send any email addresses over to the get_wishlist method for retrieval. Here’s what the handle_call looks like:
handle_call(Email_addr, _From, State) ->
%Reply back with the result from get_wishlist
Reply = get_wishlist(Email_addr),
{reply, Reply, State}.
The rest of the functions look pretty much as they did before so I won’t put them here. One other change I made was to start_link to have it also run inets:start() so we can make the http requests in the other functions.
Here’s how the thing works:
[zeusfaber@der-dieb ebin]$ erl
Erlang (BEAM) emulator version 5.6.5 [source] [64-bit] [smp:2] [async-threads:0] [hipe] [kernel-poll:false]Eshell V5.6.5 (abort with ^G)
1> c(‘../src/amazon_wishlist_otp.erl’).
{ok,amazon_wishlist_otp}
2> amazon_wishlist_otp:start_link().
ok
3> gen_server:call(amazon_wishlist_otp, “SOMEADDR@SOMEPLACE.com”).
[["Algorithms on Strings, Trees and Sequences: Computer Science and Computational Biology",
"Algorithms: Sequential, Parallel, and Distributed",
"Starting Forth: An Introduction to the Forth Language and Operating System for Beginners and Professionals (Prentice-Hall Software Series)",
"Biobazaar: The Open Source Revolution and Biotechnology",
"Nmap Network Scanning: The Official Nmap Project Guide to Network Discovery and Security Scanning",
"American Nerd: The Story of My People",
"FreeDarko presents The Macrophenomenal Pro Basketball Almanac: Styles, Stats, and Stars in Today's Game",
"CP Technologie USB TO SERIAL ADAPTER ( CP-US-03 )",
"Made to Stick: Why Some Ideas Survive and Others Die"]]
1. Your README simply has you bypass the server with a call to the presently unexported get_wishlist/1.
2. The point of a server (to throttle hits to a foreign server, for politeness or compliance) can be done ‘on the side’, as so:
delay() -> case whereis(delicious_delayer) of undefined -> register(delicious_delayer,spawn(fun delayer/0)), delay(); P -> P ! self(), receive {ok, P} -> ok end end.
3. check_status/1 looks much nicer as
check_status({“HTTP/1.1″, 200, “OK”}) -> ok;
check_status(S) -> exit({bad_status, S}).
4. On line 137, you have [T || T <- Titles] …
5. LIST_ID_URL contains “&&”
6. Why don’t you just define a val/1 ?
@ayrnieu, regarding #1 this has been fixed, I mistakenly didn’t check in the latest version of the code. Thanks for the info on the rest although val/1 is defined, unless I am misunderstanding.
I mean, why do you have
-define(Val(X),
(fun() ->
[ V || #xmlElement{ content = [#xmlText{value = V}|_]}
[ V || #xmlElement{ content = [#xmlText{value = V}|_]} <- X]
?
… again, the fail. Why do you have a macro instead of a function?
To be honest I cannot recall, I wrote that bit of the code a while ago. I believe I may have seen an xmerl example like that. Is there any issue with doing it like that, performance or otherwise?
Also if you have changes you would like to contribute to the code you are more than welcome to submit them on github or to me directly.