|
|
|
@@ -5,6 +5,7 @@ import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
|
|
"git.cin.su/m/Assistant/contracts/authority"
|
|
|
|
|
"git.cin.su/m/Assistant/contracts/continuity"
|
|
|
|
|
"git.cin.su/m/Assistant/contracts/identity"
|
|
|
|
|
continuitydomain "git.cin.su/m/Assistant/modules/continuity/domain"
|
|
|
|
@@ -217,17 +218,16 @@ func (r *ContinuityRepository) ResponseCandidates(ctx context.Context, owner ide
|
|
|
|
|
return nil, fmt.Errorf("invalid response candidate query")
|
|
|
|
|
}
|
|
|
|
|
rows, err := r.pool.Query(ctx, `SELECT
|
|
|
|
|
a.attention_item_id,a.owner_principal_id,a.scope_id,a.source_kind,a.source_prospective_item_id,a.level,a.state,a.summary,
|
|
|
|
|
a.due_at_unix_millis,a.created_at_unix_millis,a.delivered_at_unix_millis,a.action_intent_id,a.authorized_action_id,a.action_attempt_id,a.delivery_outcome,
|
|
|
|
|
a.response_id,a.response_utterance_id,a.response_operation,a.response_outcome,a.responded_at_unix_millis,a.revision,
|
|
|
|
|
COALESCE(a.attention_item_id,''),COALESCE(a.owner_principal_id,''),COALESCE(a.scope_id,''),COALESCE(a.source_kind,''),COALESCE(a.source_prospective_item_id,''),COALESCE(a.level,''),COALESCE(a.state,''),COALESCE(a.summary,''),
|
|
|
|
|
COALESCE(a.due_at_unix_millis,0),COALESCE(a.created_at_unix_millis,0),COALESCE(a.delivered_at_unix_millis,0),COALESCE(a.action_intent_id,''),COALESCE(a.authorized_action_id,''),COALESCE(a.action_attempt_id,''),COALESCE(a.delivery_outcome,''),
|
|
|
|
|
COALESCE(a.response_id,''),COALESCE(a.response_utterance_id,''),COALESCE(a.response_operation,''),COALESCE(a.response_outcome,''),COALESCE(a.responded_at_unix_millis,0),COALESCE(a.revision,0),
|
|
|
|
|
p.prospective_item_id,p.commitment_id,p.owner_principal_id,p.scope_id,p.goal_id,p.source_intent_id,p.source_utterance_id,p.summary,p.trigger_at_unix_millis,p.state,p.revision
|
|
|
|
|
FROM continuity.attention_items a
|
|
|
|
|
JOIN continuity.prospective_items p ON p.prospective_item_id=a.source_prospective_item_id
|
|
|
|
|
WHERE a.owner_principal_id=$1
|
|
|
|
|
AND a.source_kind=$2
|
|
|
|
|
AND a.state IN ($3,$4,$5)
|
|
|
|
|
FROM continuity.prospective_items p
|
|
|
|
|
LEFT JOIN continuity.attention_items a ON a.source_kind=$2 AND a.source_prospective_item_id=p.prospective_item_id AND a.owner_principal_id=p.owner_principal_id
|
|
|
|
|
WHERE p.owner_principal_id=$1
|
|
|
|
|
AND (a.attention_item_id IS NULL OR a.state IN ($3,$4,$5))
|
|
|
|
|
AND p.state IN ($6,$7)
|
|
|
|
|
ORDER BY a.delivered_at_unix_millis DESC, a.due_at_unix_millis DESC, a.attention_item_id DESC
|
|
|
|
|
ORDER BY COALESCE(a.delivered_at_unix_millis,0) DESC, p.trigger_at_unix_millis DESC, p.prospective_item_id DESC
|
|
|
|
|
LIMIT $8`,
|
|
|
|
|
owner, continuity.AttentionSourceProspectiveReminder, continuity.AttentionDelivered, continuity.AttentionPending,
|
|
|
|
|
continuity.AttentionFailed, continuity.ProspectiveDelivered, continuity.ProspectiveArmed, limit)
|
|
|
|
@@ -238,20 +238,45 @@ func (r *ContinuityRepository) ResponseCandidates(ctx context.Context, owner ide
|
|
|
|
|
var candidates []continuitydomain.ResponseCandidate
|
|
|
|
|
for rows.Next() {
|
|
|
|
|
var candidate continuitydomain.ResponseCandidate
|
|
|
|
|
var attentionID, attentionOwner, attentionScope, sourceKind, sourceProspective, level, attentionState, attentionSummary string
|
|
|
|
|
var actionIntent, authorizedAction, actionAttempt, deliveryOutcome, responseID, responseUtterance, responseOperation, responseOutcome string
|
|
|
|
|
var dueAt, createdAt, deliveredAt, respondedAt int64
|
|
|
|
|
var attentionRevision uint64
|
|
|
|
|
if err := rows.Scan(
|
|
|
|
|
&candidate.Attention.ID, &candidate.Attention.OwnerPrincipalID, &candidate.Attention.ScopeID, &candidate.Attention.SourceKind,
|
|
|
|
|
&candidate.Attention.SourceProspectiveID, &candidate.Attention.Level, &candidate.Attention.State, &candidate.Attention.Summary,
|
|
|
|
|
&candidate.Attention.DueAtUnixMillis, &candidate.Attention.CreatedAtUnixMillis, &candidate.Attention.DeliveredAtUnixMillis,
|
|
|
|
|
&candidate.Attention.ActionIntentID, &candidate.Attention.AuthorizedActionID, &candidate.Attention.ActionAttemptID,
|
|
|
|
|
&candidate.Attention.DeliveryOutcome, &candidate.Attention.ResponseID, &candidate.Attention.ResponseUtteranceID,
|
|
|
|
|
&candidate.Attention.ResponseOperation, &candidate.Attention.ResponseOutcome, &candidate.Attention.RespondedAtUnixMillis,
|
|
|
|
|
&candidate.Attention.Revision,
|
|
|
|
|
&attentionID, &attentionOwner, &attentionScope, &sourceKind, &sourceProspective, &level, &attentionState, &attentionSummary,
|
|
|
|
|
&dueAt, &createdAt, &deliveredAt, &actionIntent, &authorizedAction, &actionAttempt, &deliveryOutcome,
|
|
|
|
|
&responseID, &responseUtterance, &responseOperation, &responseOutcome, &respondedAt, &attentionRevision,
|
|
|
|
|
&candidate.Prospective.ID, &candidate.Prospective.CommitmentID, &candidate.Prospective.OwnerPrincipalID,
|
|
|
|
|
&candidate.Prospective.ScopeID, &candidate.Prospective.GoalID, &candidate.Prospective.SourceIntentID,
|
|
|
|
|
&candidate.Prospective.SourceUtteranceID, &candidate.Prospective.Summary, &candidate.Prospective.TriggerAtUnixMillis,
|
|
|
|
|
&candidate.Prospective.State, &candidate.Prospective.Revision); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("scan human response candidate: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if attentionID != "" {
|
|
|
|
|
candidate.Attention = continuity.AttentionItem{
|
|
|
|
|
ID: continuity.AttentionItemID(attentionID),
|
|
|
|
|
OwnerPrincipalID: identity.PrincipalID(attentionOwner),
|
|
|
|
|
ScopeID: authority.ScopeID(attentionScope),
|
|
|
|
|
SourceKind: continuity.AttentionSourceKind(sourceKind),
|
|
|
|
|
SourceProspectiveID: continuity.ProspectiveItemID(sourceProspective),
|
|
|
|
|
Level: continuity.AttentionLevel(level),
|
|
|
|
|
State: continuity.AttentionState(attentionState),
|
|
|
|
|
Summary: attentionSummary,
|
|
|
|
|
DueAtUnixMillis: dueAt,
|
|
|
|
|
CreatedAtUnixMillis: createdAt,
|
|
|
|
|
DeliveredAtUnixMillis: deliveredAt,
|
|
|
|
|
ActionIntentID: continuity.CommittedActionIntentID(actionIntent),
|
|
|
|
|
AuthorizedActionID: continuity.CommittedAuthorizedActionID(authorizedAction),
|
|
|
|
|
ActionAttemptID: continuity.CommittedActionAttemptID(actionAttempt),
|
|
|
|
|
DeliveryOutcome: deliveryOutcome,
|
|
|
|
|
ResponseID: continuity.HumanResponseID(responseID),
|
|
|
|
|
ResponseUtteranceID: responseUtterance,
|
|
|
|
|
ResponseOperation: continuity.HumanResponseOperation(responseOperation),
|
|
|
|
|
ResponseOutcome: continuity.ResponseOutcome(responseOutcome),
|
|
|
|
|
RespondedAtUnixMillis: respondedAt,
|
|
|
|
|
Revision: continuity.AttentionRevision(attentionRevision),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
candidates = append(candidates, candidate)
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Err(); err != nil {
|
|
|
|
@@ -292,6 +317,9 @@ func (r *ContinuityRepository) ApplyHumanResponse(ctx context.Context, response
|
|
|
|
|
if tag.RowsAffected() != 1 {
|
|
|
|
|
return ErrProspectiveStateConflict
|
|
|
|
|
}
|
|
|
|
|
if response.TargetAttentionID == "" {
|
|
|
|
|
return ErrAttentionNotFound
|
|
|
|
|
}
|
|
|
|
|
if err = markAttentionResponded(ctx, tx, response, continuity.AttentionResolved); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
@@ -306,8 +334,10 @@ func (r *ContinuityRepository) ApplyHumanResponse(ctx context.Context, response
|
|
|
|
|
if tag.RowsAffected() != 1 {
|
|
|
|
|
return ErrProspectiveStateConflict
|
|
|
|
|
}
|
|
|
|
|
if err = markAttentionResponded(ctx, tx, response, continuity.AttentionResolved); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
if response.TargetAttentionID != "" {
|
|
|
|
|
if err = markAttentionResponded(ctx, tx, response, continuity.AttentionResolved); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case continuity.ResponseCancel:
|
|
|
|
|
tag, err := tx.Exec(ctx, `UPDATE continuity.prospective_items SET state=$1, revision=revision+1
|
|
|
|
@@ -320,10 +350,15 @@ func (r *ContinuityRepository) ApplyHumanResponse(ctx context.Context, response
|
|
|
|
|
if tag.RowsAffected() != 1 {
|
|
|
|
|
return ErrProspectiveStateConflict
|
|
|
|
|
}
|
|
|
|
|
if err = markAttentionResponded(ctx, tx, response, continuity.AttentionSuppressed); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
if response.TargetAttentionID != "" {
|
|
|
|
|
if err = markAttentionResponded(ctx, tx, response, continuity.AttentionSuppressed); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case continuity.ResponseAcknowledge, continuity.ResponseDismiss:
|
|
|
|
|
if response.TargetAttentionID == "" {
|
|
|
|
|
return ErrAttentionNotFound
|
|
|
|
|
}
|
|
|
|
|
if err = markAttentionResponded(ctx, tx, response, continuity.AttentionResolved); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|