Skip to content

Commit

Permalink
fix: make reconfigure safe
Browse files Browse the repository at this point in the history
  • Loading branch information
Gu1nness committed Sep 17, 2024
1 parent a477ac5 commit 09ec58a
Showing 1 changed file with 36 additions and 35 deletions.
71 changes: 36 additions & 35 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,43 +639,39 @@ def _on_relation_handler(self, event: RelationEvent) -> None:
if not (self.unit.is_leader() and event.unit) or not self.db_initialised:
return

# Reconfigure replica set if needed.
self._reconfigure_replica_set()
# If needed, reconfigure replicaset (eg : network cut)
try:
self._reconfigure_replica_set()
self.__add_members_to_replicaset(event)
except NotReadyError:
self.status.set_and_share_status(WaitingStatus("waiting to reconfigure replica set"))
logger.error("Deferring reconfigure: another member doing sync right now")
event.defer()
except PyMongoError as e:
self.status.set_and_share_status(WaitingStatus("waiting to reconfigure replica set"))
logger.error("Deferring reconfigure: error=%r", e)
event.defer()

def __add_members_to_replicaset(self, event: RelationEvent):
with MongoDBConnection(self.mongodb_config) as mongo:
try:
replset_members = mongo.get_replset_members()
# compare set of mongod replica set members and juju hosts to avoid the unnecessary
# reconfiguration.
if replset_members == self.mongodb_config.hosts:
return
replset_members = mongo.get_replset_members()
# compare set of mongod replica set members and juju hosts to avoid the unnecessary
# reconfiguration.
if replset_members == self.mongodb_config.hosts:
return

for member in self.mongodb_config.hosts - replset_members:
logger.debug("Adding %s to replica set", member)
with MongoDBConnection(
self.mongodb_config, member, direct=True
) as direct_mongo:
if not direct_mongo.is_ready:
self.status.set_and_share_status(
WaitingStatus("waiting to reconfigure replica set")
)
logger.debug("Deferring reconfigure: %s is not ready yet.", member)
event.defer()
return
mongo.add_replset_member(member)
self.status.set_and_share_status(ActiveStatus())
except NotReadyError:
self.status.set_and_share_status(
WaitingStatus("waiting to reconfigure replica set")
)
logger.error("Deferring reconfigure: another member doing sync right now")
event.defer()
except PyMongoError as e:
self.status.set_and_share_status(
WaitingStatus("waiting to reconfigure replica set")
)
logger.error("Deferring reconfigure: error=%r", e)
event.defer()
for member in self.mongodb_config.hosts - replset_members:
logger.debug("Adding %s to replica set", member)
with MongoDBConnection(self.mongodb_config, member, direct=True) as direct_mongo:
if not direct_mongo.is_ready:
self.status.set_and_share_status(
WaitingStatus("waiting to reconfigure replica set")
)
logger.debug("Deferring reconfigure: %s is not ready yet.", member)
event.defer()
return
mongo.add_replset_member(member)
self.status.set_and_share_status(ActiveStatus())

def _on_leader_elected(self, event: LeaderElectedEvent) -> None:
"""Generates necessary keyfile and updates replica hosts."""
Expand Down Expand Up @@ -777,7 +773,12 @@ def _on_update_status(self, event: UpdateStatusEvent):
return

# If needed, reconfigure replicaset (eg : network cut)
self._reconfigure_replica_set()
try:
self._reconfigure_replica_set()
except ServerSelectionTimeoutError as e:
self.status.set_and_share_status(WaitingStatus("waiting to reconfigure replica set"))
logger.error("Deferring reconfigure: error=%r", e)
return

# Cannot check more advanced MongoDB statuses if mongod hasn't started.
with MongoDBConnection(self.mongodb_config, "localhost", direct=True) as direct_mongo:
Expand Down

0 comments on commit 09ec58a

Please sign in to comment.