Chuck Remes
2008-Nov-20 10:53 UTC
[Eventmachine-talk] [Q] need guidance on wrapping an API
I have a socket-based API service I need to consume. I want to wrap the API up in some nice ruby classes exposed via EM. The way the API works is it takes an ASCII string of the following form: RID FS FID FS value FS ... FIDn FS value_n RS where RID = record id (integer) FS = field separator FID = field id (integer) value = field value (integer or string) RS = record separator The API service returns its results using the same format. Let''s suppose the API exposes a way to add an item to inventory. I have a C header file with a bunch of enumerators and it defines INVENTORY_ADD_ITEM as the integer 7. Further, it takes two fields as parameters which are also defined as enumerations which are PRODUCT_ID 35 and QUANTITY 54. Assume the field separator is a semi-colon '';'' and the record separator is a newline. A response record will contain record INVENTORY_RESPONSE (44) with fields PRODUCT_ID (35), QUANTITY (54), MINIMUM_LEVEL (72) and PRICE (121). I want to add the product Foo with product id 123456 and a quantity of 1000. The request to the API would look like: 7;35;123456;54;1000 and the response record would look like: 44;35;123456;54;1000;72;500;121;17.85 Over a year ago I wrote a Protocol class for EM that was a subclass of EM::Connection for a different project. Is that what I should do here? Ideally I would like to be able call methods on my Protocol that do the right thing and provide a way to return classes (or Structs) that expose the returned data. Continuing the example above, my ruby Protocol class might look something like this: class Protocol < LineAndTextProtocol # assume post_init and other necessary methods are overridden correctly def initialize super @responses = Hash.new { |h, k| h[k] = [] } end # convenience method for adding to inventory def add_to_inventory(product_id, quantity) request "#{INVENTORY_ADD_ITEM }#{FS}#{PRODUCT_ID}#{FS}#{product_id}#{FS}#{QUANTITY}#{FS}#{quantity}" send_data request end # convenience method to get oldest inventory response def inventory_response @responses[INVENTORY_RESPONSE].unshift unless @responses[INVENTORY_RESPONSE].empty? end def receive_data(data) super # use LineAndTextProtocol''s method... added here for clarity end # override LineAndTextProtocol method def receive_line(line) fields = line.split(FS) case rid = fields.first do when INVENTORY_RESPONSE obj = InventoryResponse.new obj.product_id = fields[2] obj.quantity = fields[4] obj.minimum_level = fields[6] obj.price = fields[8] @responses[INVENTORY_RESPONSE] << obj else puts "do not recognize this record ID [#{fields.first}]" end end end Is this the right approach? If not, what do you suggest? cr
take a look in the ''protocols'' directory there''s some example readers in there I believe, though I shouldn''t talk having never really looked at any of them or done anything similar, myself. -=R> Is this the right approach? If not, what do you suggest?If your approach works then go for it. Nobody''s wrong here :) -=R
Chuck Remes
2008-Nov-20 12:00 UTC
[Eventmachine-talk] [Q] need guidance on wrapping an API
On Nov 20, 2008, at 1:48 PM, Roger Pack wrote:> take a look in the ''protocols'' directory there''s some example readers > in there I believe, though I shouldn''t talk having never really looked > at any of them or done anything similar, myself. > -=R > > >> Is this the right approach? If not, what do you suggest? > > If your approach works then go for it. Nobody''s wrong here :)I''ve been going through the HttpClient code in the protocols directory for the last few hours (since I posted my original message). I like the use of Deferrables here but I''d like to see how HttpClient (and Deferrables) is handled in the context of an actual client (or server) program. It''s a little hard to wrap my head around right now since I only see the Protocol definition but I''ll keep banging on it. I''ll search around for some other code that uses EM to use as larger examples. Pointers welcome, of course. cr
Chuck Remes
2008-Nov-20 16:43 UTC
[Eventmachine-talk] [Q] need guidance on wrapping an API
On Nov 20, 2008, at 2:00 PM, Chuck Remes wrote:> > On Nov 20, 2008, at 1:48 PM, Roger Pack wrote: > >> take a look in the ''protocols'' directory there''s some example readers >> in there I believe, though I shouldn''t talk having never really >> looked >> at any of them or done anything similar, myself. >> -=R >> >> >>> Is this the right approach? If not, what do you suggest? >> >> If your approach works then go for it. Nobody''s wrong here :) > > I''ve been going through the HttpClient code in the protocols > directory for the last few hours (since I posted my original > message). I like the use of Deferrables here but I''d like to see how > HttpClient (and Deferrables) is handled in the context of an actual > client (or server) program. It''s a little hard to wrap my head > around right now since I only see the Protocol definition but I''ll > keep banging on it.I''ve decided to write some code and let that be my guide. I''ll report back what I find. cr