docs: def _on_connect(self, participant):
          """Called from the WebSocket consumer. Checks if all players in the group
          have connected; runs :meth:`when_all_players_ready` once all connections
          are established.
          """
          lock = get_redis_lock()
          if not lock:
              lock = fake_lock()
  
          with lock:
              self.refresh_from_db()
              if self.ran_ready_function:
                  return
              for player in self.get_players():
                  if Connection.objects.filter(participant__code=player.participant.code).count() == 0:
                      return
                      
              self.when_all_players_ready()
              self.ran_ready_function = timezone.now()
              self.save()
  
              self.send('state', 'period_start')
  
              if self.period_length():
                  # TODO: Should replace this with something like Huey/Celery so it'll survive a server restart.
                  self._timer = threading.Timer(
                      self.period_length(),
                      lambda: self.send('state', 'period_end'))
                  self._timer.start()