nsmcp::QuestionService method run (public)

 <instance of nsmcp::QuestionService[i]> run handle turn

Defined in /usr/local/ns/tcl/nsmcp/question-service.tcl

Execute a queued conversation turn. Resolve retained owner/provider state, invoke the selected backend and publish completion, failure or cancellation under the mutex.

Parameters:
handle (required)
Retained job or conversation handle; ownership and expiry checks still apply.
turn (required)
Retained turn identifier, used to reject superseded callbacks.
Returns:
The worker callback result; conversation state retains the outcome.

Testcases:
No testcase defined.
Source code:
ns_mutex lock ${:mutex}
try {
    if {![nsv_exists ${:store} $handle]} {
        return
    }
    set record [nsv_get ${:store} $handle]
    if {[dict get $record current] ne $turn} {
        return
    }
    if {[dict get $record status] in {cancelling cancelled}} {
        set skip true
    } else {
        set skip false
        dict set record status running
        nsv_set ${:store} $handle $record
    }
    set state [dict get $record state]
    if {[dict exists $record stateEncoding]} {
        set state [encoding convertfrom utf-8 [zlib decompress $state]]
    }
    set backendName [:defaultBackend]
    if {[dict exists $record backend]} {
        set backendName [dict get $record backend]
    }
    set entry [lindex [dict get $record turns] end]
    set question [expr {[dict exists $entry backendQuestion] ? [dict get $entry backendQuestion] : [dict get $entry question]}]
} finally {
    ns_mutex unlock ${:mutex}
}
# A timed-out turn may have started a job without publishing provider
# history. Carry its handle explicitly into the next question.
if {[dict exists $record browserTimezone]} {
    append question "\nBrowser timezone context: [dict get $record browserTimezone]. Use this timezone for unspecified time windows and displayed times, unless the question explicitly requests another timezone."
}
set pendingJobs {}
foreach previous [dict get $record turns] {
    if {![dict exists $previous jobs]} {
        continue
    }
    dict for {jobHandle job} [dict get $previous jobs] {
        dict set job needsRetrieval [expr {[dict get $previous status] in {failed cancelled}
            || [dict get $job status] in {queued running}}]
        dict set pendingJobs $jobHandle $job
    }
}
dict for {jobHandle job} $pendingJobs {
    if {[dict get $job needsRetrieval]} {
        append question "\nExisting background jobHandle $jobHandle ([dict get $job name]); retrieve it with log_results rather than starting it again."
    }
}
set error {}
set status cancelled
if {!$skip} {
    if {[catch {
        [:provider $backendName] run $question $state [list [self] event $handle $turn]
    } status]} {
        set error $status
        set status failed
    }
}
ns_mutex lock ${:mutex}
try {
    if {![nsv_exists ${:store} $handle]} {
        return
    }
    set record [nsv_get ${:store} $handle]
    if {[dict get $record current] ne $turn} {
        return
    }
    if {[dict get $record status] eq "cancelling"} {
        set status cancelled
        set error {}
    }
    dict set record status $status
    set last [lindex [dict get $record turns] end]
    dict set last status $status
    dict set last error $error
    if {[dict exists $last submittedMs]} {
        dict set last elapsedMs [expr {max(0,[clock milliseconds]-[dict get $last submittedMs])}]
    }
    :logQuestion finished $record $last
    dict set record turns [lreplace [dict get $record turns] end end $last]
    nsv_set ${:store} $handle $record
} finally {
    ns_mutex unlock ${:mutex}
}
XQL Not present:
Generic, PostgreSQL, Oracle
[ hide source ] | [ make this the default ]
Show another procedure: