Skip to content

Commit

Permalink
Use korpRequest in KwicProxy
Browse files Browse the repository at this point in the history
  • Loading branch information
arildm committed Jan 13, 2025
1 parent 71f4749 commit 48c0a83
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 129 deletions.
10 changes: 5 additions & 5 deletions app/scripts/backend/base-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@ import { calcProgress } from "./common"

/** The Proxy classes wrap API requests with pre-/postprocessing and progress reporting. */
export default abstract class BaseProxy<K extends keyof API> {
pendingRequests: JQuery.jqXHR[]

constructor() {
this.pendingRequests = []
}
abortController: AbortController
pendingRequests: JQuery.jqXHR[] = []

expandCQP(cqp: string): string {
try {
Expand All @@ -24,9 +21,12 @@ export default abstract class BaseProxy<K extends keyof API> {

resetRequest(): void {
this.abort()
this.abortController = new AbortController()
}

/** Abort any running request */
abort(): void {
this.abortController?.abort()
this.pendingRequests.forEach((req) => req.abort())
}

Expand Down
84 changes: 34 additions & 50 deletions app/scripts/backend/kwic-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import _ from "lodash"
import settings from "@/settings"
import BaseProxy from "@/backend/base-proxy"
import { locationSearchGet, Factory, ajaxConfAddMethod } from "@/util"
import { ProgressReport, Response } from "./types"
import { locationSearchGet, Factory } from "@/util"
import { ProgressReport } from "./types"
import { QueryParams, QueryResponse } from "./types/query"
import { AjaxSettings } from "@/jquery.types"
import { korpRequest } from "./common"

export class KwicProxy extends BaseProxy<"query"> {
prevCQP?: string
Expand All @@ -19,17 +19,14 @@ export class KwicProxy extends BaseProxy<"query"> {
this.prevParams = null
}

makeRequest(
async makeRequest(
options: KorpQueryRequestOptions,
page: number | undefined,
progressCallback: (data: ProgressReport<"query">) => void,
kwicCallback: (data: Response<QueryResponse>) => void
): JQuery.jqXHR<Response<QueryResponse>> {
const self = this
progressCallback?: (data: ProgressReport<"query">) => void,
kwicCallback?: (data: QueryResponse) => void
): Promise<QueryResponse> {
this.resetRequest()
if (!kwicCallback) {
throw new Error("No callback for query result")
}
const abortSignal = this.abortController.signal

if (!options.ajaxParams.within) {
_.extend(options.ajaxParams, settings.corpusListing.getWithinParameters())
Expand All @@ -45,7 +42,7 @@ export class KwicProxy extends BaseProxy<"query"> {

const command = options.ajaxParams.command || "query"

const data: QueryParams = {
const params: QueryParams = {
default_context: settings.default_overview_context,
...getPageInterval(),
...options.ajaxParams,
Expand Down Expand Up @@ -76,51 +73,38 @@ export class KwicProxy extends BaseProxy<"query"> {
}
}

if (data.cqp) {
data.cqp = this.expandCQP(data.cqp)
if (params.cqp) {
params.cqp = this.expandCQP(params.cqp)
}
this.prevCQP = data.cqp
this.prevCQP = params.cqp

data.show = _.uniq(["sentence"].concat(show)).join(",")
data.show_struct = _.uniq(show_struct).join(",")
params.show = _.uniq(["sentence"].concat(show)).join(",")
params.show_struct = _.uniq(show_struct).join(",")

if (locationSearchGet("in_order") != null) {
data.in_order = false
params.in_order = false
}

this.prevParams = data
const ajaxSettings = {
url: settings.korp_backend_url + "/" + command,
data: data,
beforeSend(req, settings) {
self.addAuthorizationHeader(req)
self.prevUrl = settings.url
},

success(data: QueryResponse, status, jqxhr) {
self.queryData = data.query_data
// Run the callback to show results, if not already done by the progress handler
if (!this.foundKwic) kwicCallback(data)
},

progress(jqxhr, e: ProgressEvent) {
// Calculate progress, used for progress bars
const progressObj = self.calcProgress(e)
if (!progressObj) return
progressCallback(progressObj)

// Show current page of results if they are available
// The request may continue to count hits in the background
if ("kwic" in progressObj.data) {
this.foundKwic = true
kwicCallback(progressObj.data as QueryResponse)
}
},
} satisfies AjaxSettings
this.prevParams = params

// If the result callback is called in the progress handler, do not do it again at finish.
const kwicCallbackOnce = _.once(kwicCallback || (() => {}))

function onProgress(progress: ProgressReport<"query">) {
if (!progress) return
progressCallback?.(progress)

// Show current page of results if they are available
// The request may continue to count hits in the background
if ("kwic" in progress.data) {
kwicCallbackOnce(progress.data as QueryResponse)
}
}

const def = $.ajax(ajaxConfAddMethod(ajaxSettings)) as JQuery.jqXHR<Response<QueryResponse>>
this.pendingRequests.push(def)
return def
const data = await korpRequest(command, params, { abortSignal, onProgress })
this.queryData = data.query_data
kwicCallbackOnce(data)
return data
}
}

Expand Down
18 changes: 4 additions & 14 deletions app/scripts/backend/stats-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { statisticsService } from "@/statistics"
import { CountParams, CountResponse, StatsColumn } from "./types/count"
import { korpRequest } from "./common"
import { expandOperators } from "@/cqp_parser/cqp"
import BaseProxy from "./base-proxy"

/** Like `CountResponse` but the stats are necessarily arrays. */
export type StatsNormalized = {
Expand Down Expand Up @@ -37,20 +38,9 @@ export function normalizeStatsData(data: CountResponse): StatsNormalized {
return { ...data, combined, corpora }
}

export class StatsProxy {
abortController: AbortController
export class StatsProxy extends BaseProxy<"count"> {
prevParams: CountParams | null = null

/** Abort any running request */
abort() {
this.abortController?.abort()
}

resetAbortController(): AbortSignal {
this.abortController = new AbortController()
return this.abortController.signal
}

makeParameters(reduceVals: string[], cqp: string, ignoreCase: boolean): CountParams {
const structAttrs = settings.corpusListing.getStructAttrs(settings.corpusListing.getReduceLang())
const groupBy: string[] = []
Expand Down Expand Up @@ -87,8 +77,8 @@ export class StatsProxy {
}

async makeRequest(cqp: string, onProgress: ProgressHandler<"count">): Promise<StatisticsWorkerResult> {
this.abort()
const abortSignal = this.resetAbortController()
this.resetRequest()
const abortSignal = this.abortController.signal

const reduceval = locationSearchGet("stats_reduce") || "word"
const reduceVals = reduceval.split(",")
Expand Down
5 changes: 5 additions & 0 deletions app/scripts/backend/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ export type API = {
params: RelationsParams
response: RelationsResponse
}
relations_sentences: {
// TODO Create correct types for `RelationSentences*`
params: QueryParams
response: QueryResponse
}
timespan: {
params: TimespanParams
response: TimespanResponse
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/components/word-picture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ angular.module("korpApp").component("wordPicture", {
<span ng-if="$ctrl.showWordClass">({{data.pos | loc:$root.lang}})</span>
</td>
<td title="mi: {{row.mi | number:2}}" class="text-right">{{row.freq}}</td>
<td ng-click="$ctrl.onClickExample(row)" class="cursor">
<td ng-click="$ctrl.onClickExample(row)" class="cursor-pointer">
<i class="fa-solid fa-magnifying-glass fa-xs ml-2"></i>
</td>
</tr>
Expand Down
46 changes: 16 additions & 30 deletions app/scripts/controllers/example_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import settings from "@/settings"
import { KwicCtrl, KwicCtrlScope } from "./kwic_controller"
import { LocationService } from "@/urlparams"
import { KwicTab, RootScope } from "@/root-scope.types"
import { Response, ProgressReport } from "@/backend/types"
import { Response } from "@/backend/types"
import { QueryResponse } from "@/backend/types/query"
import { UtilsService } from "@/services/utils"
import "@/services/utils"
Expand All @@ -20,8 +20,7 @@ type ExampleCtrlScope = ScopeBase & {
hitsPictureData?: any
hitspictureClick?: (page: number) => void
kwicTab: KwicTab
makeRequest: (isPaging?: boolean) => JQuery.jqXHR<Response<QueryResponse>>
onExampleProgress: (progressObj: ProgressReport<"query">, isPaging?: boolean) => void
makeRequest: (isPaging?: boolean) => Promise<void>
setupReadingWatch: () => void
superRenderResult: (data: Response<QueryResponse>) => void
}
Expand Down Expand Up @@ -97,7 +96,7 @@ class ExampleCtrl extends KwicCtrl {
s.setupReadingWatch()
}

s.makeRequest = () => {
s.makeRequest = async () => {
const items_per_page = Number($location.search().hpp || settings["hits_per_page_default"])
const opts = s.kwicTab.queryParams

Expand All @@ -123,40 +122,27 @@ class ExampleCtrl extends KwicCtrl {
_.extend(opts.ajaxParams, { context, default_context: preferredContext })

s.loading = true
if (opts.ajaxParams.command == "relations_sentences") {
s.onExampleProgress = () => {}
} else {
s.onExampleProgress = s.onProgress
}

const def = s.proxy.makeRequest(
opts,
undefined,
(progressObj) => $timeout(() => s.onExampleProgress(progressObj)),
(data) => {
$timeout(() => {
s.renderResult(data)
s.renderCompleteResult(data)
s.loading = false
})
}
)

def.fail(() => {
const data = await s.proxy.makeRequest(opts, undefined).catch((error) => {
// AbortError is expected if a new search is made before the previous one is finished
if (error.name == "AbortError") return
$timeout(() => {
// TODO it could be abort
s.error = true
s.loading = false
})
})
$timeout(() => {
s.loading = false
})

return def
if (data) {
$timeout(() => {
s.renderResult(data)
s.renderCompleteResult(data)
})
}
}

if (s.kwicTab.queryParams) {
s.makeRequest().then(() => {
// s.onentry()
})
s.makeRequest()
}
}

Expand Down
48 changes: 19 additions & 29 deletions app/scripts/controllers/kwic_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export type KwicCtrlScope = TabHashScope & {
/** Number of search hits, may change while search is in progress. */
hitsInProgress?: number
hitsPerPage?: `${number}` | number
ignoreAbort?: boolean
initialSearch?: boolean
isReadingMode: () => boolean
kwic?: ApiKwic[]
Expand Down Expand Up @@ -114,6 +113,8 @@ export class KwicCtrl implements IController {

s.$on("abort_requests", () => {
s.proxy.abort()
s.aborted = true
s.loading = false
})

s.readingChange = function () {
Expand Down Expand Up @@ -207,39 +208,28 @@ export class KwicCtrl implements IController {
s.loading = true
s.aborted = false

s.ignoreAbort = Boolean(s.proxy.hasPending())

const ajaxParams = s.buildQueryOptions(isPaging)

const req = s.getProxy().makeRequest(
{ ajaxParams },
s.page,
(progressObj) => $timeout(() => s.onProgress(progressObj, isPaging)),
(data) => $timeout(() => s.renderResult(data))
)
req.done((data: Response<QueryResponse>) => {
$timeout(() => {
s.loading = false
s.renderCompleteResult(data, isPaging)
s.getProxy()
.makeRequest(
{ ajaxParams },
s.page,
(progressObj) => $timeout(() => s.onProgress(progressObj, isPaging)),
(data) => $timeout(() => s.renderResult(data))
)
.then((data) => {
$timeout(() => {
s.loading = false
s.renderCompleteResult(data, isPaging)
})
})
})

req.fail((jqXHR, status, errorThrown) => {
$timeout(() => {
console.log("kwic fail")
if (s.ignoreAbort) {
console.log("stats ignoreabort")
return
}
s.loading = false

if (status === "abort") {
s.aborted = true
} else {
.catch((error) => {
// AbortError is expected if a new search is made before the previous one is finished
if (error.name == "AbortError") return
$timeout(() => {
s.error = true
}
})
})
})
}

s.getProxy = () => {
Expand Down

0 comments on commit 48c0a83

Please sign in to comment.