I think what I did was setup a controller function and then another worker function which ran each operation. It had to be done this way for the similar reasons: user data might crash the process, but in that case only a single record would be affected. So in the worker function, catch the exception, and return 0 or 1 based on success/failure. On failure, run another function to do your logging.
This is always the case in pl, even if you can catch an exception, you cannot continue in the body of the function and you have to cleanup and return.
Moving stuff around inside the database is always going to be much quicker than going back and forth to the webserver for control.