Example #1
0
    def execute_futures(self, scope: str = ''):
        '''
        Execute all the registered futures in a new task

        :param scope: scoped futures to execute. Leave default for normal behavior
        '''
        return execute.execute_futures(scope)
Example #2
0
    async def initialize(self, app=None):
        # loop
        self.app = app
        while True:
            got_obj = False
            try:
                func, tvars = await self.queue.get()
                got_obj = True
                load_task_vars(tvars)
                txn = get_transaction()
                tm = get_tm()
                if txn is None or (
                    txn.status in (Status.ABORTED, Status.COMMITTED, Status.CONFLICT) and txn._db_conn is None
                ):
                    txn = await tm.begin()
                else:
                    # still finishing current transaction, this connection
                    # will be cut off, so we need to wait until we no longer
                    # have an active transaction on the reqeust...
                    await self.add((func, tvars))
                    await asyncio.sleep(1)
                    continue

                try:
                    await func()
                    await tm.commit(txn=txn)
                except Exception as e:
                    logger.error("Exception on writing execution", exc_info=e)
                    await tm.abort(txn=txn)
            except (
                RuntimeError,
                SystemExit,
                GeneratorExit,
                KeyboardInterrupt,
                asyncio.CancelledError,
                KeyboardInterrupt,
            ):
                # dive, these errors mean we're exit(ing)
                self._exceptions = True
                return
            except Exception as e:  # noqa
                self._exceptions = True
                logger.error("Worker call failed", exc_info=e)
            finally:
                if got_obj:
                    execute.execute_futures()
                    self.queue.task_done()
Example #3
0
    async def __aexit__(self, exc_type, exc, tb):
        if self.adopt_parent_txn and self.previous_txn is not None:
            # take on parent's modified, added, deleted objects if necessary
            # before we commit or abort this transaction.
            # this is necessary because inside this block, the outer transaction
            # could have been attached to an object that changed.
            # we're ready to commit and we want to potentially commit everything
            # where, we we're adopted those objects with this transaction
            if self.previous_txn != self.txn:
                # try adopting currently registered objects
                self.txn.modified = {
                    **self.previous_txn.modified,
                    **self.txn.modified
                }
                self.txn.deleted = {
                    **self.previous_txn.deleted,
                    **self.txn.deleted
                }
                self.txn.added = {**self.previous_txn.added, **self.txn.added}

                self.adopt_objects(self.previous_txn.modified, self.txn)
                self.adopt_objects(self.previous_txn.deleted, self.txn)
                self.adopt_objects(self.previous_txn.added, self.txn)

        if self.abort_when_done:
            await self.tm.abort(txn=self.txn)
        else:
            await self.tm.commit(txn=self.txn)

        if self.adopt_parent_txn and self.previous_txn is not None:
            # restore transaction ownership of item from adoption done above
            if self.previous_txn != self.txn:
                # we adopted previously detetected transaction so now
                # we need to clear changed objects and restore ownership
                self.previous_txn.modified = {}
                self.previous_txn.deleted = {}
                self.previous_txn.added = {}

                for ob in self.adopted:
                    ob.__txn__ = self.previous_txn

        if self.execute_futures:
            from guillotina.utils import execute
            execute.execute_futures()
Example #4
0
    async def evolve(self, container: IContainer):
        async with transaction():
            cur_gen = await self._get_curr_gen()
            evolvers = self._get_evolvers(cur_gen)

        if len(evolvers) > 0:
            logger.info(f"Start evolving container {container}")
            for gen, evolver in evolvers:
                async with transaction():
                    logger.info(
                        f"Evolving from generation '{cur_gen}' to '{gen}'")
                    await evolver(container)
                    cur_gen = await self._update_curr_gen(gen)

                logger.info("Executing futures")
                task = execute_futures()
                if task:
                    await task
                clear_futures()

            logger.info(f"Container {container} is now at generation {gen}")
        else:
            logger.info(f"Container already at latest generation")