Coverage report: /development/source/library/org/datagraph/spocq-shard/src/core/conditions.lisp
| Kind | Covered | All | % |
| expression | 102 | 451 | 22.6 |
| branch | 1 | 6 | 16.7 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;; -*- Mode: lisp; Syntax: ansi-common-lisp; Base: 10; Package: org.datagraph.spocq.implementation; -*-
3
(in-package :org.datagraph.spocq.implementation)
5
(:documentation "conditions"
6
"The conditions reflect two situations: either an error occurs because some aspect of the query was
7
incorrectly specified, or an error occures because the implementation is at fault. In the first case,
8
the circumstance is signaled as REQUEST-ERROR, in order to indicate, that the client must correct the
9
query. In the second case, the circumstance is signaled as a RUNTIME-ERROR wrapped around the unexpected
12
(defgeneric error-task (condition)
13
(:method ((condition t))
16
(define-condition spocq.e:error (simple-error)
18
:initarg :query :initarg :task :initform (or *task* *query*)
19
:reader error-query :reader error-task
20
:documentation "The query for which the error occured.")
22
:initarg :expression :initform nil
23
:reader error-expression
24
:documentation "Binds the expression which caused the error."))
25
(:report spocq.e:report-condition)
26
(:default-initargs :format-control ""))
28
;; the standard operators are plain functions
29
(defmethod error-format-control ((error spocq.e:error))
30
(simple-condition-format-control error))
32
(defmethod error-format-arguments ((error spocq.e:error))
33
(simple-condition-format-arguments error))
36
(defmethod print-object ((object spocq.e:error) (stream t))
39
(spocq.e:report-condition object stream)))
42
(defmethod print-object ((object spocq.e:error) (stream t))
45
(defmethod spocq.e:report-condition ((condition spocq.e:error) stream)
46
(format stream "While processing~@[ query ~a~], an error was signaled~@[: ~?~]"
47
(error-query condition)
48
(error-format-control condition)
49
(error-format-arguments condition)))
52
(defgeneric error-task-agent (condition)
53
(:method ((condition spocq.e:error))
54
(let ((task (error-task condition))) (when task (task-agent task)))))
56
(defgeneric error-task-id (condition)
57
(:method ((condition spocq.e:error))
58
(let ((task (error-task condition))) (when task (task-id task)))))
60
(defgeneric error-user-id (condition)
61
(:method ((condition spocq.e:error))
62
(let ((task (error-task condition))) (when task (task-user-id task)))))
64
(defgeneric error-repository-id (condition)
65
(:method ((condition spocq.e:error))
66
(let* ((task (error-task condition))
67
(repository (when task (task-repository task))))
68
(when repository (repository-id repository)))))
70
(defgeneric error-content-type (condition)
71
(:method ((condition spocq.e:error))
72
(let ((task (error-task condition))) (when task (task-response-content-type task)))))
74
(defgeneric error-request-exchange (condition)
75
(:method ((condition spocq.e:error))
76
(let ((task (error-task condition))) (when task (task-request-exchange task)))))
78
(defgeneric error-routing-key (condition)
79
(:method ((condition spocq.e:error))
80
(let ((task (error-task condition))) (when task (task-request-routing-key task)))))
83
(define-condition wrapped-condition-error (condition)
85
:initarg :condition :initform nil
86
:reader error-condition
87
:documentation "Binds the wrapped runtime error.")))
90
(define-condition spocq.e:runtime-error (spocq.e:error wrapped-condition-error)
92
(:documentation "A wrapper around an 'inadvertent' runtime error to permit filtering and packaging as an
93
error response. This applies to conditions such as compilation errors or reduction errors, in which
94
cases it is not necessary to cycle the broker connection."))
96
(defmethod spocq.e:report-condition ((condition spocq.e:runtime-error) stream)
98
(format stream "~@[The internal-condition was: ~a~]"
99
(error-condition condition)))
102
(define-condition spocq.e:request-error (spocq.e:error wrapped-condition-error)
104
:initarg :agent :initform nil
105
:reader error-agent)))
107
(defun spocq.e:request-error (format-control &rest format-arguments)
108
(error 'spocq.e:request-error
109
:format-control format-control
110
:format-arguments format-arguments))
113
(define-condition spocq.e:argument-type-error (spocq.e:request-error type-error)
116
:reader type-error-operator))
118
:format-control "The argument value ~s to operator '~a' is not of the required '~a' type."))
120
(defmethod error-format-arguments ((condition spocq.e:argument-type-error))
121
(list (type-error-datum condition)
122
(type-error-operator condition)
123
(type-error-expected-type condition)))
125
(defun spocq.e:argument-type-error (&rest args &key datum operator expected-type)
126
(declare (ignore datum operator expected-type))
127
(apply #'error 'spocq.e::argument-type-error args))
129
(defmacro invalid-argument-type (operator variable type)
130
`(error 'spocq.e:argument-type-error :datum ,variable :expected-type ',type
132
:format-control ,(format nil "~s: the ~a argument (~~s) must be of type ~a." operator variable type)
133
:format-arguments (list ,variable)))
135
(define-condition spocq.e::incommensurable-arguments-error (spocq.e:request-error type-error)
138
:reader type-error-operator))
141
:format-control "The argument values (~{~s, ~s~}) to operator '~a' are not comparable."))
143
(defmethod error-format-arguments ((condition spocq.e::incommensurable-arguments-error))
144
(list (type-error-datum condition)
145
(type-error-operator condition)))
147
(defun spocq.e::incommensurable-arguments-error (&rest args &key datum operator)
148
(declare (ignore datum operator ))
149
(apply #'error 'spocq.e::incommensurable-arguments-error args))
153
(define-condition spocq.e:authorization-error (spocq.e:request-error)
155
:initform nil :initarg :operation
156
:reader error-operation)
158
:initform nil :initarg :location
159
:reader error-location)))
161
(defun spocq.e:authorization-error (&rest args &key operation location agent)
162
(declare (ignore operation location agent ))
163
(apply #'error 'spocq.e:authorization-error args))
166
(define-condition spocq.e:api-authorization-error (spocq.e:authorization-error)
169
:format-control "API access is not authorized: operation '~a'")
171
"An error which concerns the authorization afforded a process given its configuration"))
173
(defmethod error-format-arguments ((condition spocq.e:api-authorization-error))
174
(list (error-operation condition)))
176
(defun spocq.e:api-authorization-error (&rest args)
177
(apply #'error 'spocq.e:api-authorization-error args))
180
(define-condition spocq.e:task-authorization-error (spocq.e:authorization-error)
183
:format-control "Resource access is not authorized: task '~a'('~a'): for '~a' to '~a'")
185
"An error which concerns the authorization to an given resource, for example a repository"))
187
(defmethod error-format-arguments ((condition spocq.e:task-authorization-error))
188
(list (error-task-id condition)
189
(error-operation condition)
190
(error-task-agent condition)
191
(or (error-location condition) (error-repository-id condition))))
193
(defun spocq.e:task-authorization-error (&rest args)
194
(apply #'error 'spocq.e:task-authorization-error args))
197
;;; (spocq.e::cardinality-limit-error :operator 'cross-join :state '(:limit 3))
198
(define-condition spocq.e::cardinality-limit-error (spocq.e:request-error type-error)
200
:initform nil :initarg :operator
201
:reader error-operator)
207
:reader error-dimensions))
209
:format-control "The operator ~a exceeded cardinality limits: ~s for ~s"))
211
(defmethod error-format-arguments ((condition spocq.e::cardinality-limit-error))
212
(list (error-operator condition)
213
(error-state condition)
214
(error-dimensions condition)))
216
(defun spocq.e::cardinality-limit-error (&rest args &key operator state dimensions)
217
(declare (ignore operator state dimensions))
218
(apply #'error 'spocq.e::cardinality-limit-error args))
222
(define-condition spocq.e:message-syntax-error (spocq.e:request-error)
224
:initform nil :initarg :operation
225
:reader error-operation)
227
:initform nil :initarg :token
230
:initform nil :initarg :byte-offset
231
:reader error-byte-offset)
233
:initform nil :initarg :line-offset
234
:reader error-line-offset)
236
:initform nil :initarg :token-offset
237
:reader error-token-offset))
239
:format-control "~@[(~a): ~]~@[task '~a': ~]~@[repository '~a': ~]Invalid message received :~@[~%Condition: ~a~]~@[~{~%failed to parse after '~a'~@[ at offset ~d~]~@[ on line ~d~]~@[ at position ~d~].~}~]~@[~%~a~]")
240
(:documentation "A message-syntax-error describes a failure to parse a query message.
241
If the information is available - eg from parse-sparql, it captures the state of the parser which
242
describes the failure. The error message includes the query expression and progress information."))
244
(defmethod error-format-arguments ((condition spocq.e:message-syntax-error))
245
(list (error-operation condition)
246
(error-task-id condition)
247
(error-repository-id condition)
248
(error-condition condition)
249
(when (error-token condition)
250
(list (error-token condition) (error-byte-offset condition) (error-line-number condition)
251
(error-token-offset condition)))
252
(error-expression condition)))
254
(defgeneric error-line-number (condition)
255
(:method ((condition spocq.e:message-syntax-error))
256
"If the condition captures the line offset, return 1+ to reflect the line number."
257
(let ((offset (error-line-offset condition)))
258
(when offset (1+ offset)))))
260
(defun spocq.e:message-syntax-error (&rest args)
261
(apply #'error 'spocq.e:message-syntax-error
264
(defun spocq.e::message-length-error (message)
265
(spocq.e::message-syntax-error :expression (string-truncate message 32)
267
:token (concatenate 'string ".." (subseq message (max 0 (- (length message) 30))))
268
:byte-offset *query-maximum-length*
270
"~@[(~a): ~]~@[task '~a': ~]~@[repository '~a': ~]Oversized message received :~@[~%Condition: ~a~]~@[~{~%failed to parse after '~a'~@[ at offset ~d~]~@[ on line ~d~]~@[ at position ~d~].~}~]~@[~%~a~]"))
272
(define-condition spocq.e:aggregate-projection-error (spocq.e:message-syntax-error )
275
(defun spocq.e::aggregate-projection-error (&rest args)
276
(apply #'error 'spocq.e::aggregate-projection-error
279
(define-condition spocq.e::resource-error (spocq.e:error)
281
:initform nil :initarg :identifier
282
:reader error-identifier))
284
:format-control "identifier: '~a'~@[, task '~a'~]~@[. repository '~a'~].")
286
"An abstract error condition restive an individual resource."))
288
(defmethod error-format-arguments ((condition spocq.e::resource-error))
289
(list* (error-identifier condition)
290
(error-task-id condition)
291
(error-repository-id condition)
294
(define-condition spocq.e:resource-not-found-error (spocq.e:resource-error)
297
"Indicate that a resource was not found at the given location in situations
298
where the value would have been required for some operation - eg as a
299
federation location, a provenance repository or as a source for secondary
300
procesing intormation"))
302
(defun spocq.e:resource-not-found-error (&rest args)
303
(apply #'error 'spocq.e:resource-not-found-error
306
(define-condition spocq.e::account-not-found-error (spocq.e:resource-not-found-error)
309
(defun spocq.e::account-not-found-error (&rest args)
310
(apply #'error 'spocq.e::account-not-found-error
313
(define-condition spocq.e:repository-not-found-error (spocq.e:resource-not-found-error)
316
(defun spocq.e:repository-not-found-error (&rest args)
317
(apply #'error 'spocq.e:repository-not-found-error
320
(define-condition spocq.e:revision-not-found-error (spocq.e:resource-not-found-error)
323
(defun spocq.e:revision-not-found-error (&rest args)
324
(apply #'error 'spocq.e:revision-not-found-error
327
(define-condition spocq.e:revision-invalid-error (spocq.e:request-error type-error)
330
(defun spocq.e:revision-invalid-error (&rest args)
331
(apply #'error 'spocq.e:revision-invalid-error
334
(define-condition spocq.e::view-not-found-error (spocq.e:resource-not-found-error)
337
(defun spocq.e::view-not-found-error (&rest args)
338
(apply #'error 'spocq.e::view-not-found-error
342
(define-condition spocq.e:resource-found-error (spocq.e:resource-error)
345
"Indicate that a resource was found at the given location in situations
346
where none should have been, for example for some operation which creates one"))
348
(defun spocq.e::resource-found-error (&rest args)
349
(apply #'error 'spocq.e:resource-found-error
352
(define-condition spocq.e:library-resource-not-found (spocq.e:resource-not-found-error)
354
:initform nil :initarg :library
355
:reader error-library))
357
:format-control "~@[task: '~a', ~]~@[repository: '~a', ~]library: '~a', location: '~a'."))
359
(defmethod error-format-arguments ((condition spocq.e:library-resource-not-found))
360
(list (error-task-id condition)
361
(error-repository-id condition)
362
(error-library condition)
363
(error-identifier condition)))
365
(defun spocq.e:library-resource-not-found (&rest args)
366
(apply #'error 'spocq.e::library-resource-not-found
370
(define-condition spocq.e:graph-management-error (spocq.e:request-error)
372
:initform nil :initarg :operation
373
:reader error-operation))
374
(:documentation "A protocol class to identify all conditions intentionally raised
375
during a graph management operation:
376
- when the source graph does not exist
377
- when an invalid graph resource identifier is specified."))
379
(defmethod error-format-arguments ((condition spocq.e:graph-management-error))
380
(list* (error-operation condition)
383
(define-condition spocq.e:graph-not-found-error (spocq.e:graph-management-error
384
spocq.e:resource-not-found-error)
387
:format-control "graph not found: operation: ~a '~a' ~@[task '~a': ~]~@[repository '~a': ~]."))
389
(defun spocq.e:graph-not-found-error (&rest args)
390
(apply #'error 'spocq.e:graph-not-found-error
393
(define-condition spocq.e:graph-found-error (spocq.e:graph-management-error
394
spocq.e:resource-found-error)
397
:format-control "graph exists: operation: ~a '~a' ~@[task '~a': ~]~@[repository '~a': ~]."))
399
(defun spocq.e::graph-found-error (&rest args)
400
(apply #'error 'spocq.e:graph-found-error
403
(define-condition spocq.e:invalid-graph-error (spocq.e:graph-management-error
404
spocq.e:resource-error)
407
:format-control "invalid graph resource: ~@[task '~a': ~]~@[repository '~a': ~]operation: ~a '~a'."))
409
(defun spocq.e:invalid-graph-error (&rest args)
410
(apply #'error 'spocq.e:invalid-graph-error
414
(define-condition invalid-token-error (spocq.e:request-error)
417
(defmethod error-format-arguments ((condition invalid-token-error))
418
(list (error-task-id condition)
419
(error-repository-id condition)
420
(error-expression condition)))
423
(define-condition spocq.e:unbound-prefix-error (invalid-token-error)
426
:format-control "~@[task '~a': ~]~@[repository '~a': ~]Unbound prefix: '~a'."))
428
(defun spocq.e:unbound-prefix-error (&rest args)
429
(apply #'error 'spocq.e:unbound-prefix-error
432
(define-condition spocq.e::vocabulary-error (invalid-token-error)
435
:format-control "~@[task '~a': ~]~@[repository '~a': ~]Invalid vocabulary term: '~a'."))
437
(defun spocq.e::vocabulary-error (&rest args)
438
(apply #'error 'spocq.e::vocabulary-error
443
(define-condition spocq.e:compilation-error (spocq.e:request-error wrapped-condition-error)
446
:format-control "Expression compilation failed :~%Condition: ~a~%Expression: ~s")
447
(:documentation "Signaled when an attempt to compile one of a query's constituent functions -
448
bgp predicate, predicate, or reduction, fails or issues a warning."))
450
(defmethod error-format-arguments ((condition spocq.e:compilation-error))
451
(list (error-condition condition) (error-expression condition)))
453
(defun spocq.e:compilation-error (&rest args &key (expression nil) (condition nil) &allow-other-keys)
454
(apply #'error 'spocq.e:compilation-error
455
:expression expression
456
:condition (or condition (make-condition 'unknown-compilation-error))
459
(define-condition unknown-compilation-error (spocq.e:compilation-error)
461
(:report (lambda (c stream)
463
(write-string "A compilation error occurred without further information." stream))))
466
(define-condition spocq.e:undefined-variable-error (spocq.e:compilation-error)
467
((variables :initarg :variables :reader error-variables))
469
:format-control "The variable~p ~s ~:[are~;is~] not defined~@[ in ~s~]."))
471
(defmethod error-format-arguments ((condition spocq.e:undefined-variable-error))
472
(let* ((variables (error-variables condition))
473
(count (length variables)))
475
(if (rest variables) variables (first variables))
477
(error-expression condition))))
479
(defun spocq.e:undefined-variable-error (&key name (expression name))
480
(error 'spocq.e:undefined-variable-error :expression expression))
483
(define-condition spocq.e:redefined-variable-error (spocq.e:compilation-error)
484
((variables :initarg :variables :reader error-variables))
486
:format-control "The variable~p ~a ~:[are~;is~] already defined~@[ in ~s~].")
488
"Indicate this as a compilation error, even though it can be deferred to extend clause execution."))
490
(defmethod error-format-arguments ((condition spocq.e:redefined-variable-error))
491
(let* ((variables (error-variables condition))
492
(count (length variables)))
494
(if (rest variables) variables (first variables))
496
(error-expression condition))))
498
(defun spocq.e:redefined-variable-error (&rest args &key variables expression)
499
(declare (ignore variables expression))
500
(apply #'error 'spocq.e:redefined-variable-error args))
503
(define-condition spocq.e:quota-error (spocq.e:request-error)
505
:initform nil :initarg :detail :reader condition-detail))
506
(:report (lambda (c stream)
507
(format stream "Expression reduction exceeded its resources~@[: ~a~]."
508
(condition-detail c))))
509
(:documentation "Signaled when a query reduction exceeds its resources."))
511
(define-condition spocq.e:timeout-error (spocq.e:quota-error)
513
(:report (lambda (c stream)
514
(format stream "Expression reduction timed out: ~a~@[: ~a~]."
515
(error-query c) (condition-detail c))))
516
(:documentation "Signaled when a query reduction times out."))
518
(defun spocq.e::timeout-error (&rest args)
519
(apply #'error 'spocq.e::timeout-error args))
521
(define-condition spocq.e:abort-error (spocq.e:runtime-error)
523
(:report (lambda (c stream)
524
(format stream "Expression reduction aborted: ~a."
526
(:documentation "Signaled when a query reduction is aborted."))
528
(defun spocq.e:abort-error (&rest args)
529
(apply #'error 'spocq.e:abort-error args))
532
(defgeneric task-errors (task)
533
(:documentation "Returns the message channel into which to place error messages
534
respective processing a given task. outside of a task environment, returns
535
the global condition channel")
537
*error-condition-channel*))
539
(defun generate-error-note (condition &key (task *query*) (channel (task-errors task)))
540
(channel-put channel (cons task condition)))
544
(define-condition spocq.e:constraint-violation (spocq.e:request-error)
546
(defun spocq.e:constraint-violation (&rest args)
547
(apply #'error 'spocq.e:constraint-violation args))
550
;;; protected operations
552
(defvar *compilation-lock*
553
#+sbcl nil ; sbcl has a global lock for the compiler
555
#-sbcl (bt:make-lock "spocq compilation"))
557
(defun spocq-compile (lambda-expression)
558
"Compile EXPRESSION with an established error and warning handler. If the compilation
559
succeeds, return the result. If an error occurs, wrap it in a compilation-error
560
and resignal that. If the compiler has suppressed and returned the error itself,
561
treat that the same as a signaled one."
563
(flet ((do-compile ()
564
(multiple-value-bind (function condition-p serious-condition-p)
565
(handler-case (compile nil lambda-expression)
566
((or warning error) (c)
567
(write-log :warn "compilation error: ~a" c) ;; macro is not around yet
568
(spocq.e:compilation-error :condition c
569
:expression lambda-expression)))
570
(declare (ignore condition-p))
571
(if serious-condition-p
572
(spocq.e:compilation-error :expression lambda-expression)
574
(if *compilation-lock*
575
(bt:with-lock-held (*compilation-lock*) (do-compile))