Network server- / client-side messaging

C

castironpi

'''
a website wants to show you different arrangements of framed pictures
on a wall. you can click, drag, scale, and rotate pictures in place.
you can also drag new pictures in to it.

spacing is uniform and settable-- if you rotate one, the readout of
the total square area changes along with the new value. you can also
select themes from the host that determine formulae for spacing, based
on established aesthetics constraints.

user clicks a picture and clicks rotate. clientside doesn't want to
transmit the whole array back to the server for calculation, but
calculation takes a long time, due to the complexity of the spacing
formulae. therefore, maintain paralell data on both sides: client for
displaying and interfacing, so as not to inform the server of every
mouse click, and server side to decrease transmission redundancy and
size. do not broadcast every click, but do not broadcast entire
interface state. constraint-based best-fit labor distribution is
between.

changes are sent to the server in the form of the change parameters
(perhaps a change object), the layout is updated roughly (still by
server-side procedures), and then precisely (along with the sq. ft.
readout) when the calculation completes. the interface remains
continuously active.

Partial cast:
'''

class PictureClientSide:
def __init__( self, image ):
self._image= image
def on_scale( self, *params ):
change= self.whatchange( scale, *params )
self.tell_the_server( change )
def on_rotate( self, *params ):
change= self.whatchange( rotate, *params )
self.tell_the_server( change )
def server_says( self, layoutchange ):
renderchange( layoutchange )

class PictureServerSide:
def __init__( self, image ):
self._image= image
def client_says( self, change ):
preliminary= self.calculation()
preliminary_change= whatchange( preliminary )
tell_the_client( preliminary_change )
completed= self.other_calculation()
completed_change= whatchange( completed )
tell_the_client( completed_change )

'''
It's too tangled to proceed. What if a second client 'change' and the
first server 'completed' cross paths? Will you cancel the first
change explicitly or just drop it? Are you shooting for five-nines
quality, or one? What about signal loss and reordering? Will you
retransmit an entire message upon suspected loss, or intervalled AYT
messages (are you there)? What about an immediate time estimate? How
general can the underlying framework be? The rest is a brainstorm.
Please critique.
'''

class PictureClientSide( ClientSide ):
settings= Setting1(), Setting2()
@incremental
def server_says( self, layoutchange ):
renderchange( layoutchange )

class PictureServerSide( ServerSide ):
settings= Setting3(), Setting4()

'''
We may want to distinguish requests in both directions. Depending on
which side takes care of the rotation, server_says may divide based on
increment.
'''

class PictureClientSide( ClientSide ):
@incremental( 1 )
def server_says( self, layoutchange ):
renderchange( layoutchange )
@incremental( 2 )
def server_says( self, layoutchange ):
renderchange( layoutchange )

'''
Furthermore, you may want the time estimate in its own method.
'''

class PictureClientSide( ClientSide ):
@incremental( layoutchange, 1 )
def server_says( self, layoutchange ):
renderchange( layoutchange )
@incremental( layoutchange, 2 )
def server_says( self, layoutchange ):
renderchange( layoutchange )
@message( timeout_message )
def timeout_message( self, etc ):
report( etc )
 
C

castironpi

'''
Last time, we left off at:
'''

class InterfaceClientSide( ClientSide ):
message= MessageDec()
incremental= message.incremental()
settings= AYT( .5, 3 )
user_act= message.out()
def __init__( self, image ):
self._image= image
ClientSide.__init__( self )
def on_scale( self, *args ):
change= self._whatchange(
self.on_scale, *args )
self.user_act( change )
def on_rotate( self, *args ):
change= self._whatchange(
self.on_rotate, *args )
self.user_act( change )
@incremental( 1 )
def layout_return( self, layoutchange ):
renderchange( layoutchange )
@incremental( 2 )
def layout_return( self, layoutchange ):
renderchange( layoutchange )
@message
def time_estimate( self, etc ):
report( etc )

class InterfaceServerSide( ServerSide ):
message= MessageDec()
incremental= message.incremental()
settings= AYT( .5, 3 )
time_estimate= message.out()
layout_return= incremental()
def __init__( self, image ):
self._image= image
ServerSide.__init__( self )
@message.intervene()
def user_act( self, change ):
etc= self.calculateeta( change )
self.time_estimate( etc )
preliminary= self.calculation()
preliminary_change= whatchange( preliminary )
self.layout_return( preliminary_change )
completed= self.other_calculation()
completed_change= whatchange( completed )
self.layout_return( completed_change )
self.layout_return.finish()

'''
Another use ClientSide and ServerSide should support is a peer-to-peer
chat-and-game server. And that said, it's not clear that there's any
distinction between ServerSide and ClientSide anyway, depending on
exactly how the listen and connect methods abstract. How much of the
implementation do they share? Most.

You could mark 'time_estimate' as incremental( 3 ); they're separated
for illustration purposes.

One remaining question is how to intervene in user_act, if a second
change arrives before the previous complete. You could combine the
earlier change parameter in the new call and throw an exception in the
thread handling the earlier one at its first loss of control--- and
maybe even at once with settrace! That tends to be costly. Not to
mention, change has already entered derived-class space. ServerSide
should make sure it's easy enough to address the issue on one's own,
and @message.nonintervene() is available too.
'''
 
C

castironpi

'''
Last time, we left off at:
'''

class InterfaceClientSide( ClientSide ):
        message= MessageDec()
        incremental= message.incremental()
        settings= AYT( .5, 3 )
        user_act= message.out()
        def __init__( self, image ):
                self._image= image
                ClientSide.__init__( self )
        def on_scale( self, *args ):
                change= self._whatchange(
                        self.on_scale, *args )
                self.user_act( change )
        def on_rotate( self, *args ):
                change= self._whatchange(
                        self.on_rotate, *args )
                self.user_act( change )
        @incremental( 1 )
        def layout_return( self, layoutchange ):
                renderchange( layoutchange )
        @incremental( 2 )
        def layout_return( self, layoutchange ):
                renderchange( layoutchange )
        @message
        def time_estimate( self, etc ):
                report( etc )

class InterfaceServerSide( ServerSide ):
        message= MessageDec()
        incremental= message.incremental()
        settings= AYT( .5, 3 )
        time_estimate= message.out()
        layout_return= incremental()
        def __init__( self, image ):
                self._image= image
                ServerSide.__init__( self )
        @message.intervene()
        def user_act( self, change ):
                etc= self.calculateeta( change )
                self.time_estimate( etc )
                preliminary= self.calculation()
                preliminary_change= whatchange( preliminary )
                self.layout_return( preliminary_change )
                completed= self.other_calculation()
                completed_change= whatchange( completed )
                self.layout_return( completed_change )
                self.layout_return.finish()

'''
Another use ClientSide and ServerSide should support is a peer-to-peer
chat-and-game server.  And that said, it's not clear that there's any
distinction between ServerSide and ClientSide anyway, depending on
exactly how the listen and connect methods abstract.  How much of the
implementation do they share?  Most.

You could mark 'time_estimate' as incremental( 3 ); they're separated
for illustration purposes.

One remaining question is how to intervene in user_act, if a second
change arrives before the previous complete.  You could combine the
earlier change parameter in the new call and throw an exception in the
thread handling the earlier one at its first loss of control--- and
maybe even at once with settrace!  That tends to be costly.  Not to
mention, change has already entered derived-class space.  ServerSide
should make sure it's easy enough to address the issue on one's own,
and @message.nonintervene() is available too.
'''

The issues over here this week were delta vs. state-- if there is a
unifiable way to specify constraints on which is cheaper given what,
and transmit it, -- and, partial inheritance of not just methods,
data: overriding 'message' and wanting -its- derivatives-- user_act,
time_estimate-- to know it, without redefining.

Obvious solutions can be redundant. self.message.layout_return is;
get 'layout_return' into the class definition. It's immediately easy
to receive the 'ServerSide' instance as a parameter-- less so to get
both it and the 'message' instance. If we can, MessageDec can include
data, but is still constrained by overriding 'message'. Conclusion?
Might as well include some data in MessageDec. How well does message=
MessageDec( ServerSide.send ) settle?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,999
Messages
2,570,243
Members
46,835
Latest member
lila30

Latest Threads

Top