Changeset - d36fd56e4b91
[Not reviewed]
0 3 0
Lance Edgar (lance) - 4 years ago 2020-10-13 17:02:57
lance@edbob.org
Allow datasync to export to rattail but *not* record changes

sometimes the "record changes" feature is desirable in all but 1 case, which is
real-time datasync, when such changes are "one way only" and have no need to
boomerang back to the originating system, and trying to do so can result in
misc. race conditions which are better avoided
3 files changed with 10 insertions and 5 deletions:
0 comments (0 inline, 0 general)
rattail/datasync/rattail.py
Show inline comments
 
@@ -312,26 +312,29 @@ class FromRattailToRattailExportConsumer(NewDataSyncImportConsumer):
 
    """
 
    handler_spec = None
 

	
 
    def __init__(self, *args, **kwargs):
 
        super(FromRattailToRattailExportConsumer, self).__init__(*args, **kwargs)
 
        self.target_engine = self.config.rattail_engines[self.dbkey]
 
        self.model = self.config.get_model()
 

	
 
    def setup(self):
 
        super(FromRattailToRattailExportConsumer, self).setup()
 
        self.topo_sortkey = make_topo_sortkey(self.model)
 

	
 
    def make_target_session(self):
 
        return Session(bind=self.target_engine)
 

	
 
    def process_changes(self, session, changes):
 
        target_session = Session(bind=self.target_engine)
 
        target_session = self.make_target_session()
 

	
 
        if self.runas_username:
 
            target_session.set_continuum_user(self.runas_username)
 

	
 
        # update all importers with current sessions
 
        for importer in self.importers.values():
 
            importer.host_session = session
 
            importer.session = target_session
 

	
 
        # topographically sort changes, i.e. per schema table dependencies.
 
        # we start with a lexical sort just for kicks maybe...
 
        class_names = set([c.payload_type for c in changes])
rattail/db/__init__.py
Show inline comments
 
@@ -36,35 +36,37 @@ else:
 

	
 
from rattail.config import ConfigExtension as BaseExtension
 

	
 

	
 
if sqlalchemy:
 

	
 
    class SessionBase(orm.Session):
 
        """
 
        Custom SQLAlchemy session class, which adds some convenience methods
 
        related to the SQLAlchemy-Continuum integration.
 
        """
 

	
 
        def __init__(self, rattail_config=None, rattail_record_changes=False, continuum_user=None, **kwargs):
 
        def __init__(self, rattail_config=None, rattail_record_changes=None, continuum_user=None, **kwargs):
 
            """
 
            Custom constructor, to allow specifying the Continuum user at session
 
            creation.  If ``continuum_user`` is specified, its value will be passed
 
            to :meth:`set_continuum_user()`.
 
            """
 
            super(SessionBase, self).__init__(**kwargs)
 
            self.rattail_config = rattail_config
 

	
 
            # maybe record changes
 
            if rattail_record_changes or getattr(self.bind, 'rattail_record_changes', False):
 
            if rattail_record_changes is None:
 
                rattail_record_changes = getattr(self.bind, 'rattail_record_changes', False)
 
            if rattail_record_changes:
 
                from rattail.db.changes import record_changes
 
                record_changes(self, config=self.rattail_config)
 
            else:
 
                self.rattail_record_changes = False
 

	
 
            if continuum_user is None:
 
                self.continuum_user = None
 
            else:
 
                self.set_continuum_user(continuum_user)
 

	
 
        def set_continuum_user(self, user_info):
 
            """
 
@@ -78,25 +80,25 @@ if sqlalchemy:
 
            if isinstance(user_info, model.User):
 
                user = self.merge(user_info)
 
            else:
 
                user = self.query(model.User).get(user_info)
 
                if not user:
 
                    try:
 
                        user = self.query(model.User).filter_by(username=user_info).one()
 
                    except NoResultFound:
 
                        user = None
 
            self.continuum_user = user
 

	
 

	
 
    Session = orm.sessionmaker(class_=SessionBase, rattail_config=None, rattail_record_changes=False, expire_on_commit=False)
 
    Session = orm.sessionmaker(class_=SessionBase, rattail_config=None, expire_on_commit=False)
 

	
 

	
 
else: # no sqlalchemy
 
    Session = None
 

	
 

	
 
class ConfigExtension(BaseExtension):
 
    """
 
    Config extension for the ``rattail.db`` subpackage.  This extension is
 
    responsible for loading the available Rattail database engine(s), and
 
    configuring the :class:`Session` class with the default engine.  This
 
    extension expects to find something like the following in your config file:
rattail/tests/db/test_init.py
Show inline comments
 
@@ -19,25 +19,25 @@ class TestSession(TestCase):
 
    def test_init_rattail_config(self):
 
        session = db.Session()
 
        self.assertIsNone(session.rattail_config)
 
        session.close()
 

	
 
        config = object()
 
        session = db.Session(rattail_config=config)
 
        self.assertIs(session.rattail_config, config)
 
        session.close()
 

	
 
    def test_init_record_changes(self):
 
        if hasattr(db.Session, 'kw'):
 
            self.assertFalse(db.Session.kw['rattail_record_changes'])
 
            self.assertIsNone(db.Session.kw.get('rattail_record_changes'))
 

	
 
        session = db.Session()
 
        self.assertFalse(session.rattail_record_changes)
 
        session.close()
 

	
 
        session = db.Session(rattail_record_changes=True)
 
        self.assertTrue(session.rattail_record_changes)
 
        session.close()
 

	
 
        engine = sa.create_engine('sqlite://')
 
        engine.rattail_record_changes = True
 
        session = db.Session(bind=engine)
0 comments (0 inline, 0 general)