Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix run operation return codes (#1377) #1406

Merged
merged 6 commits into from
Apr 25, 2019

Conversation

beckjake
Copy link
Contributor

Fixes #1377

When we run an operation, set the return code on error.

Also, since wilt-chamberlain totally broke the run-operation command in multiple ways, I fixed all that. And added tests so I don't do that again.

I also added a commit call that happens after successfully executing the macro. Maybe that would be better as a flag? I just wanted it for testing, but I can't really see not wanting to commit.

Jacob Beck added 3 commits April 17, 2019 11:26
Make dbt run-operation actually function at all with the RPC changes
On exceptions that occur outside of actual macro execution, catch them and return failure appropriately
Copy link
Member

@cmcarthur cmcarthur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. @drewbanin should we document run-operation in wilt chamberlain?

@@ -22,19 +21,44 @@ def _get_macro_parts(self):
def _get_kwargs(self):
return dbt.utils.parse_cli_vars(self.args.args)

def run(self):
def run_unsafe(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make this _run_unsafe

@drewbanin
Copy link
Contributor

@cmcarthur yeah, I think Wilt is the right time to release this for real.

@beckjake I think it's actually pretty important that we don't add a commit at the end of operations. Some queries (like vacuum / analyze on Redshift) are not allowed to run inside of transactions. I think that if people want to run transactional code through operations, they should add the begin and commit explicitly.

If we do this, then we need to be really sure that we don't begin a transaction implicitly, otherwise the query won't be committed. Do we have a good way of ensuring that connections never have open connections when the operations SQL runs?

result = self._run_unsafe()
except dbt.exceptions.Exception as exc:
logger.error(
'Encountered a dbt exception while running a macro: {}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an exception that dbt is aware of, but it's not a dbt exception per se. I just don't want folks to think that dbt did something wrong if their operations fail. Can we make this say:

Encountered an error while running an operation:

@beckjake
Copy link
Contributor Author

Some queries (like vacuum / analyze on Redshift) are not allowed to run inside of transactions. I think that if people want to run transactional code through operations, they should add the begin and commit explicitly.

Ok, I can do that instead then.

If we do this, then we need to be really sure that we don't begin a transaction implicitly, otherwise the query won't be committed.

I think that's already true. If your macro is implemented via call statement currently like I kind of assume it is, you must make sure not set auto_begin=False. Right?

Do we have a good way of ensuring that connections never have open connections when the operations SQL runs?

I assume you mean "... connections never have open transactions ...". Yeah. adapter.clear_transaction() is reliable, in my experience.

Copy link
Contributor

@drewbanin drewbanin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great - good call on adding tests.

One thing: I think we'll want to clear the transaction before calling the operation macro. This is helpful for queries (like vacuum) that must be run outside of a transaction:

{% macro vacuum() %}
  {% call statement(auto_begin=false) %}
    vacuum public.events
  {% endcall %}
{% endmacro %}

If you invoke this operation, you'll see:

VACUUM cannot run inside a transaction block

I don't actually see an explicit begin; in the logs, so I think this is that psycopg2 thing where new connections are created with an open transaction. I assumed that setting auto_begin=false would prevent this from happening, but maybe we can be heavy-handed and just add

adapter.clear_transaction()

right before the call to adapter.execute_macro()

This seems to work ok, and I believe it no-ops on databases that don't have transactions.

.format(exc)
)
logger.debug('', exc_info=True)
return False, None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we conceivably return a dict that encodes this error message? That would be useful for an eventual API that wants to do something with the results when an operation fails.

I think we can leave this as-is for now, but want to keep it in the back of our minds when we revisit the RunResults node contract.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, though in the RPC case I'd probably reach for overriding the run method entirely (the message would end up in the response logs anyway)

Copy link
Contributor

@drewbanin drewbanin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@beckjake beckjake merged commit 5762e5f into dev/wilt-chamberlain Apr 25, 2019
@beckjake beckjake deleted the fix/run-operation-return-codes branch April 25, 2019 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fail with nonzero exit code if run-operation task encounters an unhandled exception
3 participants