Skip to content
Browse files

[fix] stdlib: Reconnect now updates seeds with current list of hosts.

  • Loading branch information...
1 parent 864899f commit b256e989f7ebfbb3dc7c0e9bced1e8e20b090a8d @nrs135 nrs135 committed with OpaOnWindowsNow Feb 1, 2012
Showing with 41 additions and 14 deletions.
  1. +24 −13 stdlib/apis/mongo/mongo.opa
  2. +17 −1 stdlib/apis/mongo/replset.opa
View
37 stdlib/apis/mongo/mongo.opa
@@ -92,8 +92,8 @@ type Mongo.srr =
/ {noconnection}
/** Messages for socket pool **/
-@private type Mongo.reconnectmsg = {reconnect:(string,Mongo.db)} / {stop}
-@private type Mongo.reconnectresult = {reconnectresult:bool} / {stopresult}
+@private type Mongo.reconnectmsg = {reconnect:(string,Mongo.db)} / {getseeds} / {stop}
+@private type Mongo.reconnectresult = {reconnectresult:option(Mongo.db)} / {getseedsresult:list(Mongo.mongo_host)} / {stopresult}
MongoDriver = {{
@@ -193,44 +193,55 @@ MongoDriver = {{
* won't ever be used but we limit the depth of the recursion.
*/
@private
- doreconnect(from:string, m:Mongo.db): bool =
+ doreconnect(from:string, m:Mongo.db): option(Mongo.db) =
do if m.log then ML.debug("MongoDriver.doreconnect","depth={m.depth}",void)
if m.depth > m.max_depth
then
do if m.log then ML.error("MongoDriver.reconnect({from})","max depth exceeded",void)
- false
+ none
else
m = {m with depth=m.depth+1}
if m.reconnectable
then
rec aux(attempts) =
if attempts > m.max_attempts
- then false
+ then none
else
(match MongoReplicaSet.connect(m) with
- | {success=_} ->
+ | {success=m} ->
do if m.log then ML.info("MongoDriver.reconnect({from})","reconnected",void)
- true
+ {some=m}
| {~failure} ->
do if m.log then ML.info("MongoDriver.reconnect({from})","failure={C.string_of_failure(failure)}",void)
do Scheduler.wait(m.reconnect_wait)
aux(attempts+1))
aux(0)
else
- false
+ none
@private
- reconfn(_, msg) =
+ reconfn(seeds, msg) =
match msg with
- | {reconnect=(from,m)} -> {return={reconnectresult=doreconnect(from,m)}; instruction={unchanged}}
+ | {reconnect=(from,m)} ->
+ match doreconnect(from,m) with
+ | {some=nm} -> {return={reconnectresult={some=nm}}; instruction={set=nm.seeds}}
+ | {none} -> {return={reconnectresult={none}}; instruction={unchanged}}
+ end
+ | {getseeds} -> {return={getseedsresult=seeds}; instruction={unchanged}}
| {stop} -> {return={stopresult}; instruction={stop}}
@private
reconnect(from, m) =
+ m =
+ match (Cell.call(m.reconncell,({getseeds}:Mongo.reconnectmsg)):Mongo.reconnectresult) with
+ | {getseedsresult=seeds} -> {m with seeds=MongoReplicaSet.mrg(seeds,m.seeds)}
+ | res -> do ML.debug("MongoDriver.reconnect","weird cell result {res}",void) m
+ end
do if m.log then ML.debug("MongoDriver.reconnect","m={m}",void)
match (Cell.call(m.reconncell,({reconnect=((from,m))}:Mongo.reconnectmsg)):Mongo.reconnectresult) with
- | {reconnectresult=tf} -> tf
- | _ -> do ML.debug("MongoDriver.reconnect","fail",void) @fail
+ | {reconnectresult={none}} -> false
+ | {reconnectresult={some=_}} -> true
+ | res -> do ML.debug("MongoDriver.reconnect","fail (result={res})",void) @fail
@private
stoprecon(m) =
@@ -422,7 +433,7 @@ MongoDriver = {{
**/
init(bufsize:int, pool_max:int, reconnectable:bool, log:bool): Mongo.db =
{ conn={none};
- reconncell=(Cell.make(void, reconfn):Cell.cell(Mongo.reconnectmsg,Mongo.reconnectresult));
+ reconncell=(Cell.make([], reconfn):Cell.cell(Mongo.reconnectmsg,Mongo.reconnectresult));
pool=SocketPool.make(("localhost",default_port),pool_max,log);
pool_max=Int.max(pool_max,1); ~bufsize; ~log;
seeds=[]; name=""; ~reconnectable;
View
18 stdlib/apis/mongo/replset.opa
@@ -192,6 +192,22 @@ MongoReplicaSet = {{
| {none} -> (m,[]))
| {failure=_} -> (m,[])
+ hostname = System.gethostname()
+ is_localhost(h:string) : bool = match h with | "localhost" -> true | "127.0.0.1" -> true | _ -> h == hostname
+ same_host(h1,h2) : bool = (is_localhost(h1) && is_localhost(h2)) || System.gethostbyname(h1) == System.gethostbyname(h2)
+ same_mongo_host((h1,p1):Mongo.mongo_host)((h2,p2):Mongo.mongo_host) = p1 == p2 && same_host(h1,h2)
+
+ mrg(l1:list(Mongo.mongo_host), l2:list(Mongo.mongo_host)) : list(Mongo.mongo_host) =
+ rec aux(l1:list(Mongo.mongo_host), l2:list(Mongo.mongo_host)) =
+ match (l2:list(Mongo.mongo_host)) with
+ | [] -> (l1:list(Mongo.mongo_host))
+ | [h|t] ->
+ match List.index_p(same_mongo_host(h), l1) with
+ | {some=_} -> (aux(l1, t):list(Mongo.mongo_host))
+ | {none} -> (aux([h|l1], t):list(Mongo.mongo_host))
+ end
+ aux(l1, l2)
+
/**
* Connect (and reconnect) to a replica set.
*
@@ -216,7 +232,7 @@ MongoReplicaSet = {{
(m,hosts) = check_seed(m)
if hosts == []
then aux(m,rest)
- else {success=(m,hosts)}
+ else {success=({m with seeds=mrg(hosts,seeds)},hosts)}
| {failure=_} ->
aux(m,rest))
| [] -> {failure={Error="MongoReplicaSet.connect: No connecting seeds"}}

0 comments on commit b256e98

Please sign in to comment.
Something went wrong with that request. Please try again.