Dave's megaref suggestion was the kind of thing I had in mind initially but 
using Agents might be make more sense.

I'm going to have a play around then report back on my progress.  Thanks 
for your thoughts, it's very much appreciated.

James







On Friday, 12 April 2013 07:52:22 UTC+1, Cedric Greevey wrote:
>
> What about a map of table IDs to agents?
>
> The map itself only needs to change if an event creates or destroys a 
> table. Anything else impacts a single table, and can be sent off to that 
> table's agent. An agent makes sense to hold each single table, as tables 
> undergo sequential transformations triggered by incoming external events.
>
> Similarly, a map of user IDs to agents can track everyone's play-money.
>
> The code that translates between incoming network events and sends to 
> agents is pretty much completely decoupled from the way the latter work, as 
> well; it won't need to be changed, for instance, if you start persisting 
> user information to a database. The money-handling agent for a user just 
> needs to now post an update to the backing database, and your startup code 
> needs to load the database data to initialize the agent contents on a 
> restart, and presto, you now have long term persistent user accounts and 
> money amounts, without touching the network/agent-send code, only the 
> functions applied to the agents.
>
> So, sorting incoming network events and calling the appropriate business 
> logic becomes a concern completely separated from implementing that 
> business logic, and from the server-side DAL, and from the outgoing 
> networking. (The agents would need to also generate outgoing network 
> packets to update clients on the state changes they should know about. For 
> example, if a player gets dealt a 5 of hearts, their client needs to be 
> told that -- the others shouldn't, of course, as otherwise it would enable 
> someone with a hacked client to cheat by peeking at other players' cards.)
>
> Timers can also be managed in a similar manner; for example, for each 
> connected client a fold-timeout agent can be created, and when the player 
> moves, the agent is sent something like this:
>
> (defn timeout-set [[_ player]]
>   (let [a *agent*]
>     (future (Thread/sleep (+ 50 timeout-duration)) (send-off a 
> timeout-check)))
>   [(+ timeout-duration (System/currentTimeMillis)) player])
>
> which depends on this:
>
> (defn timeout-check [[timeout-time player]]
>   (if (<= timeout-time (System/currentTimeMillis))
>     (do
>       (send-off player timed-out)
>       [Long/MAX_VALUE player])
>     [timeout-time player]))
>
> which will send "timed-out" to the player-agent if they don't move for 
> timeout-duration milliseconds. When the player moves, timeout-set both sets 
> the earliest time they may now time out (current time + timeout-duration) 
> and creates a sleeping thread that will wake up a little bit later than 
> then and send the agent a timeout-check. (Since *agent* won't be the same 
> in that thread and when it wakes up, it's saved into a closed-over local in 
> timeout-set.) The timeout-check function sees if the agent's stored timeout 
> value has been exceeded; if not the player must have moved again in the 
> interim and it returns the agent's current state, leaving it undisturbed. 
> Otherwise, it maxes out the timeout time and sends a timed-out signal to 
> the player's agent. The player can't get timed out a second time until 
> moving again first, which would bring the timeout time back down out of the 
> stratosphere. The timeout time for a player would also be set to this when 
> there was no hand in progress, and on first connecting.
>
> Of course, the above could need to be adapted to your needs. Also, I'm 
> unsure how big a thread pool you'd get with future; very many connected 
> clients might swamp it with long-sleeping threads. Using the executor 
> framework stuff from Java might be a better idea, or even more agents (and 
> send-off rather than send), if you want it to scale, though using a future 
> makes the example code above very simple and easy to understand.
>
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to