Re: Mixed Sync/Async communications pattern



On Thu, 10 Apr 2008 09:12:48 -0700 (PDT),
"dave.joubert@xxxxxxxxxxxxxx" <dave.joubert@xxxxxxxxxxxxxx> wrote:

My thinking at the moment revolves around a FIFO queue of expected
responses, but someone may already have solved the problem.

I think the reason you haven't got any replies, is that it's been
solved 101 different ways, and very few of them lend themselves to
anything particularly generic.


You seem to be on the right track to me... Another option is to give
each message a unique ID, and have that ID send back in the reply, and
use the ID to index an array of pending transactions. That way, you
don't even need to worry about the messages coming back in order, for
example, if you're requesting information which needs to be fetched
from a database.

Although in that case it is a good idea to be able to "expire" (or even
re-try) messages that for some reason weren't responded to at all.
I've had that happen with a Windoze "business server" that had a
too-small output buffer, and ended up just ditching messages when it
was under pressure. It's almost expected if you're communicating using
UDP to a remote server, and so forth.

But with reliable communications, a fifo queue aught to do just fine,
and is much less complicated, so if it'll do, then do it that way.
Although a transaction ID can still be useful to detecting if the whole
thing gets fowled up. ;)

I've also had to deal with one case where several modules within an
application would make similar (or even identical) requests, which
needed to be merged and batched. Usually the first one would set up a
timeout, after which the requests gathered so far would be sent off in a
single chunk. The response then needed to be divided up and fed back
to whomever had requested it, sometimes needing to take care to
respond in the same order that an individual requestee had asked for.
On that occasion the requests typically took a while to process, being
handed off to other servers to process at the remote end, so there were
usually several requests in the pipeline at any given time and the
responses would come back in an unpredictable order. So you'd send off
requests for all the information you know you'll be needing (and
occasionally even some you _might_ need), and then have to collect
together the responses until you have the ones you need to proceed,
every so often having to stop and wait for another piece of information
if it hasn't come back yet. It's all still the same sort of task.


Something that may be worth looking at (apart from continuations which
we don't have yet, but would be absolutely fantastic for this sort of
thing), are functions that package the current procedures variables
into a dict or similar. There's a few in the wiki that'll do the
job, and can be useful if you either just need to invoke a short script
when the request completes, or if you're invoking a follow-on procedure
which can simply use [dict with] to unpack the variables passed to it as
an argument, and continue on where the previous stage left off. That
leads to this sort of structure;

proc something:real {state env} {
switch -exact -- $part "start" {
dict with env {
... do some stuff ...
}
request-blah ... [list something:real part1 $env]
} "part1" {
dict with env {
... do some more stuff ...
}
request-blah ... [list something:real part2 $env]
} ...etc...
}
proc something {...whatever...} {
... check argument correctness ...
# grab initial environment
foreach _ [info locals] {dict set env $_ [set $_]}
# call the real thing
something:real start $env
}

Where [capture] performs that [foreach] to build the env dict within an
[uplevel], and uses [info level] to obtain the calling procs name, then
sandwiches those two around the supplied next-state value. Not going
to try write [capture] on the fly, there are good examples in the wiki
and it can be a little tricky to get right without trampling stuff
(the only "safe" way that I'm aware of off-hand, is to wrap [info
locals] in an uplevel, and then one-by-one [upvar] each variable and
add it to the dict).

I've never personally had need to go quite that far (usually
[namespace code] is all I've needed), although I did write something up
just to see how it'd look. I used a proc-like command that took
multiple body portions, and essentially did exactly what I described
there. It pretty much worked, but not quite to my liking, so I put it
aside somewhere (alas, I've got an awful lot of "somewhere" on my
system ;) ) to finish off if I ever had a real need for it.


Hope that gives you a few extra ideas? (Sorry for the late reply, I
must have marked the thread as read by accident. I've done this sort
of things a couple times myself, so I know how pesky it can be.)


Fredderic
.



Relevant Pages

  • Re: Bandwidth constraint causing IIS/ASP.NET problem
    ... > We simulated too many clients, making requests faster than the ... > bandwidth on that part of the network could consume the responses. ...
    (microsoft.public.dotnet.framework.aspnet)
  • Re: Dont BOUNCE the list!
    ... I have received responses regarding filtering (requests for ... filtering, requests for greater granularity, requests for whitelists) ... The typical response is "We don't ...
    (Security-Basics)
  • Re: Windows 2003 external nslookup times out, internal works
    ... My firewall does not log responses to DNS (or any other ... ports), only the initial requests. ...
    (microsoft.public.windows.server.dns)
  • Re: Allgemeiner Vergleich von Daten
    ... Die SRC_IP des Requests soll mit der DST_IP des Responses ... hab das ganze mal in einer VIEW gemacht und auch nur für eine einzige ... mydb.test.TYPE LIKE "Request" AND mydb.test.SRC_IP LIKE ...
    (de.comp.datenbanken.mysql)
  • Re: ASP Takes Over The Server
    ... > This occuring when no one is on the application, it is like some sort of ... The aspnet_wp process primarily handles requests and responses. ... I suggest checking the IIS logs and system event logs. ...
    (microsoft.public.dotnet.framework.aspnet)