| Filename | /home/mickey/git_tree/PONAPI/Server/lib/PONAPI/Exception.pm |
| Statements | Executed 18 statements in 755µs |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 12µs | 3.04ms | PONAPI::Exception::BEGIN@4 |
| 1 | 1 | 1 | 9µs | 49µs | PONAPI::Exception::BEGIN@7 |
| 1 | 1 | 1 | 9µs | 40µs | PONAPI::Exception::BEGIN@15 |
| 1 | 1 | 1 | 8µs | 70µs | PONAPI::Exception::BEGIN@151 |
| 1 | 1 | 1 | 7µs | 102µs | PONAPI::Exception::BEGIN@5 |
| 0 | 0 | 0 | 0s | 0s | PONAPI::Exception::__ANON__[lib/PONAPI/Exception.pm:27] |
| 0 | 0 | 0 | 0s | 0s | PONAPI::Exception::__ANON__[lib/PONAPI/Exception.pm:48] |
| 0 | 0 | 0 | 0s | 0s | PONAPI::Exception::_bad_req |
| 0 | 0 | 0 | 0s | 0s | PONAPI::Exception::_handle_exception_obj |
| 0 | 0 | 0 | 0s | 0s | PONAPI::Exception::_moose_type_to_nice_description |
| 0 | 0 | 0 | 0s | 0s | PONAPI::Exception::as_response |
| 0 | 0 | 0 | 0s | 0s | PONAPI::Exception::as_string |
| 0 | 0 | 0 | 0s | 0s | PONAPI::Exception::new_from_exception |
| 0 | 0 | 0 | 0s | 0s | PONAPI::Exception::throw |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | # ABSTRACT: Exceptions for PONAPI::Server | ||||
| 2 | package PONAPI::Exception; | ||||
| 3 | |||||
| 4 | 2 | 53µs | 2 | 6.07ms | # spent 3.04ms (12µs+3.03) within PONAPI::Exception::BEGIN@4 which was called:
# once (12µs+3.03ms) by PONAPI::DAO::Request::Role::UpdateLike::BEGIN@7 at line 4 # spent 3.04ms making 1 call to PONAPI::Exception::BEGIN@4
# spent 3.03ms making 1 call to Moose::import |
| 5 | 2 | 25µs | 2 | 198µs | # spent 102µs (7+95) within PONAPI::Exception::BEGIN@5 which was called:
# once (7µs+95µs) by PONAPI::DAO::Request::Role::UpdateLike::BEGIN@7 at line 5 # spent 102µs making 1 call to PONAPI::Exception::BEGIN@5
# spent 95µs making 1 call to Sub::Exporter::__ANON__[Sub/Exporter.pm:337] |
| 6 | |||||
| 7 | 2 | 70µs | 2 | 90µs | # spent 49µs (9+40) within PONAPI::Exception::BEGIN@7 which was called:
# once (9µs+40µs) by PONAPI::DAO::Request::Role::UpdateLike::BEGIN@7 at line 7 # spent 49µs making 1 call to PONAPI::Exception::BEGIN@7
# spent 40µs making 1 call to Exporter::import |
| 8 | |||||
| 9 | sub throw { | ||||
| 10 | my $class_or_obj = shift; | ||||
| 11 | die ( blessed $class_or_obj ? $class_or_obj : $class_or_obj->new(@_) ); | ||||
| 12 | } | ||||
| 13 | |||||
| 14 | use overload | ||||
| 15 | 1 | 5µs | 1 | 31µs | # spent 40µs (9+31) within PONAPI::Exception::BEGIN@15 which was called:
# once (9µs+31µs) by PONAPI::DAO::Request::Role::UpdateLike::BEGIN@7 at line 16 # spent 31µs making 1 call to overload::import |
| 16 | 1 | 524µs | 1 | 40µs | fallback => 1; # spent 40µs making 1 call to PONAPI::Exception::BEGIN@15 |
| 17 | |||||
| 18 | 1 | 2µs | 1 | 1.66ms | has message => ( # spent 1.66ms making 1 call to Moose::has |
| 19 | is => 'ro', | ||||
| 20 | isa => 'Str', | ||||
| 21 | required => 1, | ||||
| 22 | ); | ||||
| 23 | |||||
| 24 | has status => ( | ||||
| 25 | is => 'ro', | ||||
| 26 | isa => 'Int', | ||||
| 27 | default => sub { 400 }, | ||||
| 28 | 1 | 3µs | 1 | 6.79ms | ); # spent 6.79ms making 1 call to Moose::has |
| 29 | |||||
| 30 | 1 | 2µs | 1 | 1.38ms | has bad_request_data => ( # spent 1.38ms making 1 call to Moose::has |
| 31 | is => 'ro', | ||||
| 32 | isa => 'Bool', | ||||
| 33 | ); | ||||
| 34 | |||||
| 35 | 1 | 2µs | 1 | 1.25ms | has sql_error => ( # spent 1.25ms making 1 call to Moose::has |
| 36 | is => 'ro', | ||||
| 37 | isa => 'Bool', | ||||
| 38 | ); | ||||
| 39 | |||||
| 40 | 1 | 2µs | 1 | 1.23ms | has internal => ( # spent 1.23ms making 1 call to Moose::has |
| 41 | is => 'ro', | ||||
| 42 | isa => 'Bool', | ||||
| 43 | ); | ||||
| 44 | |||||
| 45 | has json_api_version => ( | ||||
| 46 | is => 'ro', | ||||
| 47 | isa => 'Str', | ||||
| 48 | default => sub { '1.0' }, | ||||
| 49 | 1 | 4µs | 1 | 2.21ms | writer => '_set_json_api_version' # spent 2.21ms making 1 call to Moose::has |
| 50 | ); | ||||
| 51 | |||||
| 52 | # Picked from Throwable::Error | ||||
| 53 | sub as_string { | ||||
| 54 | my $self = shift; | ||||
| 55 | return $self->message; | ||||
| 56 | } | ||||
| 57 | |||||
| 58 | sub as_response { | ||||
| 59 | my $self = shift; | ||||
| 60 | |||||
| 61 | my $status = $self->status; | ||||
| 62 | my $detail = $self->message; | ||||
| 63 | |||||
| 64 | if ( $self->sql_error ) { | ||||
| 65 | $detail = "SQL error: $detail"; | ||||
| 66 | } | ||||
| 67 | elsif ( $self->bad_request_data ) { | ||||
| 68 | $detail = "Bad request data: $detail"; | ||||
| 69 | } | ||||
| 70 | else { | ||||
| 71 | $status = 500; | ||||
| 72 | warn $detail if $detail; | ||||
| 73 | $detail = "A fatal error has occured, please check server logs"; | ||||
| 74 | } | ||||
| 75 | |||||
| 76 | return $status, [], +{ | ||||
| 77 | jsonapi => { version => $self->json_api_version }, | ||||
| 78 | errors => [ { detail => $detail, status => $status } ], | ||||
| 79 | }; | ||||
| 80 | } | ||||
| 81 | |||||
| 82 | sub new_from_exception { | ||||
| 83 | my ( $class, $e ) = @_; | ||||
| 84 | |||||
| 85 | return $e if blessed($e) && $e->isa($class); | ||||
| 86 | |||||
| 87 | my %args_for_new = $class->_handle_exception_obj($e); | ||||
| 88 | |||||
| 89 | unless ( $args_for_new{status} and $args_for_new{message} ) { | ||||
| 90 | %args_for_new = ( | ||||
| 91 | status => 500, | ||||
| 92 | message => '', | ||||
| 93 | ); | ||||
| 94 | warn "$e"; | ||||
| 95 | } | ||||
| 96 | |||||
| 97 | return $class->new(%args_for_new); | ||||
| 98 | } | ||||
| 99 | |||||
| 100 | sub _handle_exception_obj { | ||||
| 101 | my ( $self, $e ) = @_; | ||||
| 102 | return unless blessed($e) or $e->isa('Moose::Exception'); | ||||
| 103 | |||||
| 104 | if ( $e->isa('Moose::Exception::AttributeIsRequired') ) { | ||||
| 105 | my $attribute = $e->attribute_name; | ||||
| 106 | return _bad_req( "Parameter `$attribute` is required" ); | ||||
| 107 | } | ||||
| 108 | elsif ( | ||||
| 109 | $e->isa('Moose::Exception::ValidationFailedForTypeConstraint') or | ||||
| 110 | $e->isa('Moose::Exception::ValidationFailedForInlineTypeConstraint') | ||||
| 111 | ) { | ||||
| 112 | my $class = find_meta( $e->class_name ); | ||||
| 113 | my $attribute = $class->get_attribute( $e->attribute_name ); | ||||
| 114 | my $value_nice = JSON::XS->new->allow_nonref->utf8->canonical->encode( $e->value ); | ||||
| 115 | |||||
| 116 | if ( !$attribute ) { | ||||
| 117 | my $attr = $e->attribute_name; | ||||
| 118 | return _bad_req( "Parameter `$attr` got an expected data type: $value_nice" ); | ||||
| 119 | } | ||||
| 120 | |||||
| 121 | my $attribute_name = $attribute->name; | ||||
| 122 | my $type_name = _moose_type_to_nice_description( $attribute->{isa} ); | ||||
| 123 | |||||
| 124 | return _bad_req( "Parameter `$attribute_name` expected $type_name, but got a $value_nice" ); | ||||
| 125 | } | ||||
| 126 | |||||
| 127 | return; | ||||
| 128 | } | ||||
| 129 | |||||
| 130 | sub _bad_req { | ||||
| 131 | return ( | ||||
| 132 | message => shift, | ||||
| 133 | status => 400, | ||||
| 134 | bad_request_data => 1, | ||||
| 135 | ); | ||||
| 136 | } | ||||
| 137 | |||||
| 138 | # THIS IS NOT COMPLETE, NOR IS IT MEANT TO BE | ||||
| 139 | sub _moose_type_to_nice_description { | ||||
| 140 | my ($type_name) = @_; | ||||
| 141 | |||||
| 142 | $type_name =~ s/ArrayRef/Collection/g; | ||||
| 143 | $type_name =~ s/HashRef/Resource/g; | ||||
| 144 | $type_name =~ s/Maybe\[(.+)]/null or $1/g; | ||||
| 145 | $type_name =~ s/\|/ or /g; | ||||
| 146 | |||||
| 147 | return $type_name; | ||||
| 148 | } | ||||
| 149 | |||||
| 150 | 1 | 3µs | 2 | 7.48ms | __PACKAGE__->meta->make_immutable; # spent 7.47ms making 1 call to Class::MOP::Class::make_immutable
# spent 12µs making 1 call to PONAPI::Exception::meta |
| 151 | 3 | 62µs | 2 | 132µs | # spent 70µs (8+62) within PONAPI::Exception::BEGIN@151 which was called:
# once (8µs+62µs) by PONAPI::DAO::Request::Role::UpdateLike::BEGIN@7 at line 151 # spent 70µs making 1 call to PONAPI::Exception::BEGIN@151
# spent 62µs making 1 call to Moose::unimport |
| 152 | |||||
| 153 | __END__ |