Exceptable - Exception Propagation for PG
Post on 19-May-2015
523 Views
Preview:
DESCRIPTION
Transcript
Exceptable
Tuesday, October 20, 2009
Exception Propagation, in PostgreSQL and PythonAurynn Shaw, Commandprompt, Inc.
PostgreSQL Conference West, 2009
Tuesday, October 20, 2009
Background
• Large, enterprise Python + Pylons application
• Simpycity ORM utilizes significant stored procedures
• Strong procedural interfaces
Tuesday, October 20, 2009
Stored Procedures are Rare
• Most people don’t use Stored Procedures.
Tuesday, October 20, 2009
The Present SystemWherein
• A Database Query
• A Stored Procedure
• Or, A Database Query
• Exceptions Galore
Tuesday, October 20, 2009
A Database Query
•The App queries the Database
Tuesday, October 20, 2009
A Database Query
• The App queries the Database
• Any variety of query
Tuesday, October 20, 2009
A Database Query
>>> c.Raw("SELECT * FROM auth_only")()
Traceback (most recent call last):
... <SNIP> ...
psycopg2.ProgrammingError: permission denied for relation auth_only
Tuesday, October 20, 2009
A Database Query
• The App queries the Database
• Any variety of query
• Or A Stored Procedure
Tuesday, October 20, 2009
Or a Stored Procedure
CREATE OR REPLACE FUNCTION except_test() RETURNS VOID AS $$
BEGIN
RAISE EXCEPTION 'Test!';
END;
$$ LANGUAGE PLPGSQL;
>>> c.Function("except_test")()
Traceback (most recent call last):
... <SNIP> ...
psycopg2.InternalError: Test!
Tuesday, October 20, 2009
Beget an Exception
• Stored procedures raise InternalErrors
• Every procedural exception becomes this
• Permissions violations raise ProgrammingErrors
• I haven’t tested if this is all PG exceptions.
Tuesday, October 20, 2009
Seriously?
• This is what we have to work with?
Tuesday, October 20, 2009
Why this is ImportantWherein
• Why?
• Defining your APIs
• Separation of Concerns
• Procedural Spaghetti
Tuesday, October 20, 2009
Why?
• Limited information to propagate upwards
• Stored Procedures are Harder to use
• Permissions violations are difficult to detect
Tuesday, October 20, 2009
API Undefined
• Exceptions are part of your API
Tuesday, October 20, 2009
API Undefined
• Exceptions are part of your API
• Easily overlooked
Tuesday, October 20, 2009
API Undefined
• Exceptions are part of your API
• Easily overlooked
• Delineations will make life easier
Tuesday, October 20, 2009
Separation of Concerns
• The Database is for Database Logic
Tuesday, October 20, 2009
Separation of Concerns
• The Database is for Database Logic
• Harder to write Data Logic
Tuesday, October 20, 2009
Spaghetti
• InternalErrors everywhere
Early version of our app didn’t have Exceptable - we were left catching InternalErrors and guessing at what the error was, based on timing.
Tuesday, October 20, 2009
Spaghetti
• InternalErrors everywhere
• Insufficiency of Information
Tuesday, October 20, 2009
Spaghetti
• InternalErrors everywhere
• Insufficiency of Information
• Considerable Repeated Code
Tuesday, October 20, 2009
A Saving Grace
• Violating Procedure Signatures -> Python DataError
Tuesday, October 20, 2009
A Better DealWherein
• Database API
• Easy Python implementation
• Universality
• Exceptable
Tuesday, October 20, 2009
Database API
• Easier to define an API
Tuesday, October 20, 2009
Database API
• Easier to define an API
• The DB becomes part of that API
Tuesday, October 20, 2009
Database API
• Easier to define an API
• The DB becomes part of that API
• Simple Stored Procedure interface
Tuesday, October 20, 2009
Database API
• Easier to define an API
• The DB becomes part of that API
• Simple Stored Procedure interface
• Easily declare new Exceptions
Tuesday, October 20, 2009
Wonderfully Python
• A Simple Decorator
Tuesday, October 20, 2009
Simply Decorated
from exceptable.exceptable import Except
base = Except()
@base
def db_function():
pass
Tuesday, October 20, 2009
Wonderfully Python
• A Simple Decorator
• Catches and re-emits Exceptions
• The core of Exceptable
• Easy to Integrate - 2 lines, in Simpycity
Tuesday, October 20, 2009
Universality
• Exceptable Procedures never change
• DB logic doesn’t change
• Application support is Easy
Tuesday, October 20, 2009
Exceptable
• More Pythonic Database Access
• Better exceptions means better app flow
Tuesday, October 20, 2009
Example CodeWherein
• The DB Library
• The Application Implementation
• Catching Permissions Violations
• PostgreSQL 8.4
Tuesday, October 20, 2009
To Start,
CREATE TABLE exceptions (
name text primary key,
description text not null,
parent text references exceptions(name)
);
INSERT INTO exceptions VALUES ('Exception', 'Base exception',NULL);
INSERT INTO exceptions VALUES ('NotFoundException', 'Could not find specified record', 'Exception');
Tuesday, October 20, 2009
Which leads to
CREATE OR REPLACE FUNCTION not_found ( in_reason TEXT) RETURNS VOID as $body$
SELECT exceptaple.raise( 'NotFoundException', $1 );
$body$ LANGUAGE SQL;
Tuesday, October 20, 2009
Application Level
• Easy to Query the Exception tables
Tuesday, October 20, 2009
Application Level
• Easy to Query the Exception tables
• Easy to set up a new library
• Python took 50 lines
Tuesday, October 20, 2009
Our Python Example
• The Exceptable decorator is easy to set up
• Designed for DB-API integration
Tuesday, October 20, 2009
In the Application
base = Except(InternalError, { 'Exception': Exception, 'NotFoundException': NotFoundError,})
Tuesday, October 20, 2009
Our Python Example
• The Exceptable decorator is easy to set up
• Designed for DB-API integration
• User-defined
Tuesday, October 20, 2009
User Definitions
base = Except(InternalError, {
'PermissionError': PermissionError,
'UnknownUser': UnknownUserError,
'NotFoundException': NotFoundError,
})
Tuesday, October 20, 2009
Our Python Example
• The Exceptable decorator is easy to set up
• Designed for DB-API integration
• User-defined, and soon, table introspection
Tuesday, October 20, 2009
base is a decorator
@basedef db_api(query): con = db.connect(conn_string) cur = con.cursor() return cur(query)
Tuesday, October 20, 2009
Which leads to
try: rs = db_api(‘select * from test_api()’)except NotFoundError, e: # A hah! A usable error! pass
Tuesday, October 20, 2009
As Opposed To
try: rs = db_api(‘select * from test_api()’)except InternalError, e: if “NotFoundException” in str(e): raise NotFoundError(str(e)) elif “PermissionsError” in str(e): raise PermissionsError(str(e))
Tuesday, October 20, 2009
Our Python Example
• The Exceptable decorator is easy to set up
• Designed for DB-API integration
• User-defined, and soon, table introspection
• Existing decorators can be expanded easily
Tuesday, October 20, 2009
Grow, my Pretties!
class NotNullError(BaseException): passclass SCE(BaseException): pass
base.add({‘NotNullException’: NotNullError,‘SufficientCoffeeException’: SCE
})
Tuesday, October 20, 2009
Permission Denied
• Exceptable.py also wraps the base permission denied
• DB permissions violations work at the app level
Tuesday, October 20, 2009
Vertically Challenged
a = c.Function(‘test_auth’);try: result = a()except PermissionDenied, e: abort(403)except NoSuchUser, e: abort(401)
Tuesday, October 20, 2009
AND THUSQuestions?
Tuesday, October 20, 2009
Get It!
https://projects.commandprompt.com/public/exceptable/
Tuesday, October 20, 2009
THANK YOU!
Tuesday, October 20, 2009
top related