= Add Custom Rattail <-> Rattail Import/Export = If you have multiple "Poser" app nodes running then you likely will need to keep data in sync between them, to some extent. Most of the work has been done for you already; however since you probably have added some custom tables etc. to the DB, you must likewise add some custom importer logic before your custom tables are fully supported. == Importer Definitions == First you should make sure to define all custom "model" (table) importers in e.g. `~/src/poser/poser/importing/model.py`. Remember, these are only responsible for defining the "target" side of the importer logic, irrespective of the data "source". Then you must declare "proper" importers for each table desired, in e.g. `~/src/poser/poser/importing/poser.py`. These will reference the "model" importers you just created, and may add any special logic needed when the data source is another Poser node (as opposed to any other system). == Import Handler Definitions == Then you must define the custom handlers, for both import and export use cases. In other words both of the following would ideally be supported: * Poser (other) -> Poser (local) aka. "import" * Poser (local) -> Poser (other) aka. "export" These again will be defined in e.g. `~/src/poser/poser/importing/poser.py` and again the goal is to specify only the custom parts. The most common use case (presumably) is one where the set of tables to be synced is the same in either direction, in other words "import vs. export" is just a matter of perspective and the logic should be identical otherwise. However it is not uncommon, for certain nodes to be considered (more) "authoritative" for some tables, in which case import vs. export may in fact differ in terms of which tables should be synced. This often happens when there are different "node types" within the overall system. In either case the approach is basically the same. You first define a "mixin" class which does nothing other than declare a set of importers which should be effective in ''either direction'' (import or export). Then you define a custom import handler, and a custom export handler; each of which will inherit from the mixin class in addition to the "true" base class. Below is an example, where all the same tables are synced in either direction. However you can can modify the `get_importers()` method of either handler, to add extra importers which should be "one direction only" etc. Again, note that the mixin class should ''only'' declare those importers which should be invoked in ''both'' directions. {{{#!highlight python from rattail.importing.rattail import FromRattailToRattailImport, FromRattailToRattailExport class FromPoserToPoserMixin(object): """ Common "mixin" class for Poser <-> Poser import/export handlers """ def add_poser_importers(self, importers): # core-extension models importers['PoserCustomer'] = PoserCustomerImporter # custom models importers['Foo'] = FooImporter importers['Bar'] = BarImporter return importers class FromPoserToPoserImport(FromRattailToRattailImport, FromPoserToPoserMixin): """ Handles the Poser (other) -> Poser (local) import """ def get_importers(self): importers = super(FromPoserToPoserImport, self).get_importers() self.add_poser_importers(importers) return importers class FromPoserToPoserExport(FromRattailToRattailExport, FromPoserToPoserMixin): """ Handles the Poser (local) -> Poser (other) export """ def get_importers(self): importers = super(FromPoserToPoserExport, self).get_importers() self.add_poser_importers(importers) return importers }}} == Config Defaults == The last piece is to make sure Rattail knows to use your custom handlers instead of the default handlers. It is of course possible to e.g. add some values to config file to accomplish this. However the more typical approach is to define the "config defaults" directly within Poser app code. Usually the place to do this is in `~/src/poser/poser/config.py` although this assumes you already have a custom `ConfigExtension` defined there. Assuming that's the case, something like the following would register your custom import/export handlers: {{{#!highlight python from rattail.config import ConfigExtension class PoserConfig(ConfigExtension): """ Custom config extension for Poser """ key = 'poser' def configure(self, config): # import handlers config.setdefault('rattail.importing', 'rattail.handler', 'poser.importing.poser:FromPoserToPoserImport') config.setdefault('rattail.exporting', 'rattail.handler', 'poser.importing.poser:FromPoserToPoserExport') }}} == Command Line == With all the above in place, you can now run the typical commands and your extra tables should be supported: {{{ cd /srv/envs/poser # to import from "other" to local DB sudo -u rattail bin/rattail -c app/quiet.conf -P import-rattail --dbkey other --dry-run # to export from local to "other" DB sudo -u rattail bin/rattail -c app/quiet.conf -P export-rattail --dbkey other --dry-run }}}