Skip to content

Commit

Permalink
fix: improve scheduling code
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-lednev committed Nov 24, 2024
1 parent 86b6b0e commit dd9b30b
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 89 deletions.
8 changes: 5 additions & 3 deletions src/service/dataview-facade.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { App } from "obsidian";
import { getAPI, STask, type DataviewApi } from "obsidian-dataview";
import { STask, type DataviewApi } from "obsidian-dataview";

import {
type Scheduler,
createBackgroundBatchScheduler,
Expand All @@ -18,7 +18,8 @@ export class DataviewFacade {
const paths: string[] = this.getDataview()?.pagePaths(source).array();

const pageQueries: Array<() => STask[]> = paths.map(
(path) => () => this.getDataview()?.page(path)?.file.tasks.array(),
(path) => () =>
this.getDataview()?.page(path)?.file.tasks.array() || [],
);

this.scheduler.enqueueTasks(pageQueries, (results) => {
Expand All @@ -27,6 +28,7 @@ export class DataviewFacade {
});
};

// todo: remove
legacy_getAllTasksFrom = (source: string) => {
return this.getDataview()?.pages(source).file.tasks.array() || [];
};
Expand Down
7 changes: 4 additions & 3 deletions src/ui/components/multi-day/multi-day-grid.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
getPreviousWorkWeek,
} from "../../../util/range";
import * as r from "../../../util/range";
import Search from "../../components/search.svelte";
import ControlButton from "../control-button.svelte";
import { createSlide } from "../defaults";
import {
Expand Down Expand Up @@ -198,9 +199,9 @@
{#if visibleSideControls === "settings"}
<SettingsControls />
{/if}
<!--{#if visibleSideControls === "search"}-->
<!-- <Search />-->
<!--{/if}-->
{#if visibleSideControls === "search"}
<Search />
{/if}
</div>
{/if}

Expand Down
7 changes: 3 additions & 4 deletions src/ui/hooks/use-dataview-tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ export function useDataviewTasks({
return derived(
[listsFromVisibleDailyNotes, tasksFromExtraSources, settingsStore],
([$listsFromVisibleDailyNotes, $tasksFromExtraSources, $settingsStore]) => {
const allTasks = dv.uniq([
...$listsFromVisibleDailyNotes,
...$tasksFromExtraSources,
]);
const allTasks = dv.uniq(
$listsFromVisibleDailyNotes.concat($tasksFromExtraSources),
);

return $settingsStore.showCompletedTasks
? allTasks
Expand Down
78 changes: 33 additions & 45 deletions src/ui/hooks/use-search.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,55 @@
import { derived, get, writable, type Readable } from "svelte/store";
import type { STask } from "obsidian-dataview";
import { derived, writable, type Readable } from "svelte/store";

import { searchResultLimit } from "../../constants";
import type { DataviewFacade } from "../../service/dataview-facade";
import * as dv from "../../util/dataview";
import { getUpdateTrigger } from "../../util/store";

import { useDebounceWithDelay } from "./use-debounce-with-delay";

export function useSearch(props: {
dataviewFacade: DataviewFacade;
dataviewTasks: Readable<Array<STask>>;
dataviewSource: Readable<string>;
taskUpdateTrigger: Readable<unknown>;
keyDown: Readable<unknown>;
}) {
const { dataviewFacade, dataviewSource, taskUpdateTrigger, keyDown } = props;
const { dataviewSource, dataviewTasks } = props;

const sourceSignal = dataviewSource;
const query = writable("");
const updateSignal = derived([taskUpdateTrigger, query], getUpdateTrigger);
// todo: pass through update signal
const debouncedSearchSignal = useDebounceWithDelay(
updateSignal,
keyDown,
250,

const matchedStasks = derived(
[query, dataviewTasks, dataviewSource],
([$query, $dataviewTasks]) =>
$query.trim().length === 0
? []
: $dataviewTasks.filter((task) =>
task.text.toLowerCase().includes($query),
),
);

const result = derived(debouncedSearchSignal, () => {
// todo: pass through update signal and remove this
const currentQuery = get(query).toLowerCase();
const currentSource = get(sourceSignal);
const description = derived(
[query, matchedStasks],
([$query, $matchedStasks]) => {
if ($query.trim().length === 0) {
return "Empty";
}

if ($matchedStasks.length === 0) {
return "No matches";
}

if (currentQuery.trim().length === 0) {
return [];
}
if ($matchedStasks.length > searchResultLimit) {
return `Limited to ${searchResultLimit} entries. Try refining your search.`;
}

return `${$matchedStasks.length} matches`;
},
);

// todo: use async
const result = derived(matchedStasks, ($matchedStasks) => {
return (
dataviewFacade
.legacy_getAllTasksFrom(currentSource)
.filter((task) => {
return task.text.toLowerCase().includes(currentQuery);
})
$matchedStasks
.slice(0, searchResultLimit)
// todo: remove moment
.map((task) => dv.toUnscheduledTask(task, window.moment()))
);
});

const description = derived([query, result], ([$query, $result]) => {
if ($query.trim().length === 0) {
return "Empty";
}

if ($result.length === 0) {
return "No matches";
}

if ($result.length > searchResultLimit) {
return `The matches are limited to ${searchResultLimit} entries. Try refining your search.`;
}

return `${$result.length} matches`;
});

return {
query,
result,
Expand Down
12 changes: 5 additions & 7 deletions src/ui/hooks/use-tasks-from-extra-sources.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { STask } from "obsidian-dataview";
import { derived, type Readable } from "svelte/store";

import { DataviewFacade } from "../../service/dataview-facade";
import type { STask } from "obsidian-dataview";

interface UseTasksFromExtraSourcesProps {
dataviewSource: Readable<string>;
Expand All @@ -17,13 +17,11 @@ export function useTasksFromExtraSources({
return derived(
[dataviewSource, refreshSignal],
([$dataviewSource], set: (tasks: STask[]) => void) => {
dataviewFacade
.getAllTasksFrom($dataviewSource)
.then(set, (reason) => {
console.error("Failed to fetch tasks from dataview source: ", reason);
dataviewFacade.getAllTasksFrom($dataviewSource).then(set, (reason) => {
console.error("Failed to fetch tasks from dataview source: ", reason);

set([]);
});
set([]);
});
},
[],
);
Expand Down
10 changes: 1 addition & 9 deletions src/util/create-hooks.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ export function useTasks(props: {
settingsStore: Writable<DayPlannerSettings>;
combinedIcalSyncTrigger: Readable<object>;
debouncedTaskUpdateTrigger: Readable<object>;
taskUpdateTrigger: Readable<object>;
keyDown: Readable<object>;
isOnline: Readable<boolean>;
visibleDays: Readable<Moment[]>;
layoutReady: Readable<boolean>;
Expand All @@ -90,8 +88,6 @@ export function useTasks(props: {
app,
dataviewSource,
currentTime,
taskUpdateTrigger,
keyDown,
workspaceFacade,
pointerDateTime,
onUpdate,
Expand Down Expand Up @@ -190,10 +186,8 @@ export function useTasks(props: {
);

const search = useSearch({
dataviewFacade,
dataviewTasks: tasksFromExtraSources,
dataviewSource,
taskUpdateTrigger,
keyDown,
});

const editContext = useEditContext({
Expand Down Expand Up @@ -308,8 +302,6 @@ export function createHooks({
app,
dataviewSource,
currentTime,
taskUpdateTrigger,
keyDown,
workspaceFacade,
onUpdate,
pointerDateTime,
Expand Down
8 changes: 6 additions & 2 deletions src/util/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export function createBackgroundBatchScheduler<T>(props: {
let tasks: Array<() => T> = [];
let currentTaskHandle: number | null = null;
let currentOnFinish: (results: T[]) => void;
let currentOnCancel: (() => void) | undefined;

function runTaskQueue(deadline: IdleDeadline) {
while (
Expand All @@ -69,14 +70,17 @@ export function createBackgroundBatchScheduler<T>(props: {
function enqueueTasks(
newTasks: Array<() => T>,
onFinish: (results: T[]) => void,
onCancel?: () => void,
) {
currentOnFinish = onFinish;

if (currentTaskHandle) {
cancelJob(currentTaskHandle);
currentOnCancel?.();
currentTaskHandle = null;
}

currentOnFinish = onFinish;
currentOnCancel = onCancel;

tasks = newTasks;
results = [];
currentTaskHandle = enqueueJob(runTaskQueue);
Expand Down
23 changes: 7 additions & 16 deletions src/util/use-remote-tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ import { isEmpty } from "lodash/fp";
import type { Moment } from "moment";
import ical from "node-ical";
import { request } from "obsidian";
import { derived, readable, type Readable } from "svelte/store";
import { derived, type Readable } from "svelte/store";

import type { DayPlannerSettings } from "../settings";
import type { RemoteTask, WithTime } from "../task-types";
import type { WithIcalConfig } from "../types";
import { useIdleDerived } from "../ui/hooks/use-idle-derived";

import { canHappenAfter, icalEventToTasks } from "./ical";
import { getEarliestMoment } from "./moment";
import {
createBackgroundBatchScheduler,
} from "./scheduler";

function isVEvent(event: ical.CalendarComponent): event is ical.VEvent {
return event.type === "VEVENT";
Expand Down Expand Up @@ -92,18 +90,11 @@ export function useRemoteTasks(props: {
},
);

const tasksFromEvents = readable<Array<ReturnType<typeof icalEventToTasks>>>(
[],
(set) => {
const scheduler = createBackgroundBatchScheduler<
ReturnType<typeof icalEventToTasks>
>({ timeRemainingLowerLimit: 10 });

return schedulerQueue.subscribe((next) => {
scheduler.enqueueTasks(next, set);
});
},
);
const tasksFromEvents = useIdleDerived({
batch: schedulerQueue,
timeRemainingLowerLimit: 10,
initial: [],
});

return derived(tasksFromEvents, ($tasksFromEvents) =>
$tasksFromEvents
Expand Down

0 comments on commit dd9b30b

Please sign in to comment.