Re: Mixed Sync/Async communications pattern
- From: Fredderic <my-name-here@xxxxxxxxxx>
- Date: Sat, 19 Apr 2008 18:20:02 +1000
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
.
- Follow-Ups:
- Re: Mixed Sync/Async communications pattern
- From: dave.joubert@xxxxxxxxxxxxxx
- Re: Mixed Sync/Async communications pattern
- References:
- Mixed Sync/Async communications pattern
- From: dave.joubert@xxxxxxxxxxxxxx
- Mixed Sync/Async communications pattern
- Prev by Date: Re: get FILE* from Tcl_Channel
- Next by Date: Re: image photo -file ... results in black image [macosx, 8.5.1, Img 1.3]
- Previous by thread: Re: Mixed Sync/Async communications pattern
- Next by thread: Re: Mixed Sync/Async communications pattern
- Index(es):
Relevant Pages
|