def testCreatingInMemoryStoreUsingConfig(self): """Full test of `construct_eventstore(...)`.""" config = configparser.ConfigParser() config.add_section("general") config.set("general", "storage-backend", "estoresection") config.add_section("estoresection") config.set("estoresection", "class", "rewind.server.eventstores.InMemoryEventStore") estore = rconfig.construct_eventstore(config) self.assertIsInstance(estore, eventstores.InMemoryEventStore)
def testCreatingInMemoryStoreUsingConfigWithGivenSection(self): """Test full test of `construct_eventstore(...)` given a section.""" config = configparser.ConfigParser() config.add_section("estoresection") # The 'general' section need not to be defined here since a section is # given to `construct_eventstore(...)` below. config.set("estoresection", "class", "rewind.server.eventstores.InMemoryEventStore") estore = rconfig.construct_eventstore(config, "estoresection") self.assertIsInstance(estore, eventstores.InMemoryEventStore)
def _testCreateCombinedRotatedLogFromConfig(self, defaults): """Creating combined rotated store from config. This class function is a helper for the actual tests. Parameters: defaults -- whether default values should be used or not for `SyncedRotationEventStores` instantiation. Can be used to toggle execution of different conditional branches to improve coverage. """ path = tempfile.mkdtemp() print("Using temporary directory:", path) config = configparser.ConfigParser() config.add_section("rotated_sqlite") config.set("rotated_sqlite", "class", "rewind.server.eventstores.RotatedEventStore") config.set("rotated_sqlite", "realclass", "rewind.server.eventstores.SQLiteEventStore") config.set("rotated_sqlite", "prefix", "sqlite") config.set("rotated_sqlite", "path", path) config.add_section("rotated_appendlog") config.set("rotated_appendlog", "class", "rewind.server.eventstores.RotatedEventStore") config.set("rotated_appendlog", "realclass", "rewind.server.eventstores.LogEventStore") config.set("rotated_appendlog", "prefix", "appendlog") config.set("rotated_appendlog", "path", path) config.add_section("synced_rotator") config.set("synced_rotator", "class", "rewind.server.eventstores.SyncedRotationEventStores") config.set("synced_rotator", "storage-backends", "rotated_sqlite rotated_appendlog") if not defaults: config.set("synced_rotator", "events_per_batch", "25000") # Random option to have coverage of logging of unknown options config.set("synced_rotator", "foo", "bar") estore = rconfig.construct_eventstore(config, "synced_rotator") self.assertIsInstance(estore, eventstores.SyncedRotationEventStores) shutil.rmtree(path)
def testCreatingSyncedRotatedLogFromConfigFromConfig(self): """Create a `RotatedEventStore` from config.""" path = tempfile.mkdtemp() print("Using temporary directory:", path) config = configparser.ConfigParser() config.add_section("rotated_sqlite") config.set("rotated_sqlite", "class", "rewind.server.eventstores.RotatedEventStore") config.set("rotated_sqlite", "realclass", "rewind.server.eventstores.SQLiteEventStore") config.set("rotated_sqlite", "prefix", "sqlite") config.set("rotated_sqlite", "path", path) estore = rconfig.construct_eventstore(config, "rotated_sqlite") self.assertIsInstance(estore, eventstores.RotatedEventStore) shutil.rmtree(path)
def from_config(config, **options): """Instantiate an `SyncedRotationEventStores` from config. Parameters: config -- the configuration file options read from file(s). **options -- various options given to the specific event store. Shall not be used with this event store. Warning will be logged for every extra non-recognized option. The only required key to this function is 'path'. returns -- a newly instantiated `SyncedRotationEventStores`. """ required_args = ('storage-backends', ) optional_args = {'events_per_batch': 25000} rconfig.check_config_options("SyncedRotationEventStores", required_args, tuple(optional_args.keys()), options) if "events_per_batch" in options: events_per_batch = int(options["events_per_batch"]) else: events_per_batch = optional_args["events_per_batch"] estore = SyncedRotationEventStores(events_per_batch) for section in options['storage-backends'].split(' '): try: substore = rconfig.construct_eventstore(config, section) estore.add_rotated_store(substore) except Exception as e: _logger.exception( 'Could not instantiate substore from' ' section %s', section) estore.close() raise return estore
def from_config(config, **options): """Instantiate an `SyncedRotationEventStores` from config. Parameters: config -- the configuration file options read from file(s). **options -- various options given to the specific event store. Shall not be used with this event store. Warning will be logged for every extra non-recognized option. The only required key to this function is 'path'. returns -- a newly instantiated `SyncedRotationEventStores`. """ required_args = ('storage-backends',) optional_args = {'events_per_batch': 25000} rconfig.check_config_options("SyncedRotationEventStores", required_args, tuple(optional_args.keys()), options) if "events_per_batch" in options: events_per_batch = int(options["events_per_batch"]) else: events_per_batch = optional_args["events_per_batch"] estore = SyncedRotationEventStores(events_per_batch) for section in options['storage-backends'].split(' '): try: substore = rconfig.construct_eventstore(config, section) estore.add_rotated_store(substore) except Exception as e: _logger.exception('Could not instantiate substore from' ' section %s', section) estore.close() raise return estore
def testInMemoryFallback(self): """Test `construct_eventstore(...)` defaults to in-memory estore.""" estore = rconfig.construct_eventstore(None) self.assertIsInstance(estore, eventstores.InMemoryEventStore)
def run(options, exit_codeword=None): """Actually execute the program. Calling this method can be done from tests to simulate executing the application from command line. Parameters: options -- `optionparser` from config file. exit_codeword -- an optional exit_message that will shut down Rewind. Used for testing. returns -- exit code for the application. Non-zero for errors. """ QUERY_ENDP_OPT = 'query-bind-endpoint' STREAM_ENDP_OPT = 'streaming-bind-endpoint' ZMQ_NTHREADS = "zmq-nthreads" if not options.has_section(config.DEFAULT_SECTION): msg = "Missing default section, `{0}`." fmsg = msg.format(config.DEFAULT_SECTION) raise config.ConfigurationError(fmsg) if not options.has_option(config.DEFAULT_SECTION, QUERY_ENDP_OPT): msg = "Missing (query) bind endpoint in option file: {0}:{1}" fmsg = msg.format(config.DEFAULT_SECTION, QUERY_ENDP_OPT) raise config.ConfigurationError(fmsg) queryendp = options.get(config.DEFAULT_SECTION, QUERY_ENDP_OPT).split(",") streamendp = _get_with_fallback(options, config.DEFAULT_SECTION, STREAM_ENDP_OPT, '').split(",") queryendp = filter(lambda x: x.strip(), queryendp) streamendp = filter(lambda x: x.strip(), streamendp) try: eventstore = config.construct_eventstore(options) except config.ConfigurationError as e: _logger.exception("Could instantiate event store from config file.") raise zmq_nthreads = _get_with_fallback(options, config.DEFAULT_SECTION, ZMQ_NTHREADS, '3') try: zmq_nthreads = int(zmq_nthreads) except ValueError: msg = "{0}:{1} must be an integer".format(config.DEFAULT_SECTION, ZMQ_NTHREADS) _logger.fatal(msg) return 1 with _zmq_context_context(zmq_nthreads) as context, \ _zmq_socket_context(context, zmq.REP, queryendp) as querysock, \ _zmq_socket_context(context, zmq.PUB, streamendp) as streamsock: # Executing the program in the context of ZeroMQ context as well as # ZeroMQ sockets. Using with here to make sure are correctly closing # things in the correct order, particularly also if we have an # exception or similar. runner = _RewindRunner(eventstore, querysock, streamsock, (exit_codeword.encode() if exit_codeword else None)) runner.run() return 0