Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion dev/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,11 @@
}

function setQueryLog() {
vg.coordinator().manager.logQueries(qlogToggle.checked);
// logQueries is no longer in use
// vg.coordinator().manager.logQueries(qlogToggle.checked);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where we should add or remove our custom observer that redirects events to console.

//
//
// Add custom observer here that redirects logs to concolse
}

function setCache() {
Expand Down
22 changes: 19 additions & 3 deletions packages/mosaic/core/src/Coordinator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { type MosaicClient } from './MosaicClient.js';
import { type SelectionClause } from './SelectionClause.js';
import { MaybeArray } from '@uwdata/mosaic-sql';
import { Table } from '@uwdata/flechette';
import { EventType } from './Events.js';
import { ObserveDispatch } from './util/ObserveDispatch.js';

interface FilterGroupEntry {
selection: Selection;
Expand Down Expand Up @@ -50,6 +52,7 @@ export class Coordinator {
public clients = new Set<MosaicClient>;
public filterGroups = new Map<Selection, FilterGroupEntry>;
protected _logger: Logger = voidLogger();
public eventBus: ObserveDispatch<any>; // temporary measures until we finalize event types
Comment thread
domoritz marked this conversation as resolved.
Outdated

/**
* @param db Database connector. Defaults to a web socket connection.
Expand Down Expand Up @@ -77,7 +80,9 @@ export class Coordinator {
consolidate = true,
preagg = {}
} = options;
this.eventBus = new ObserveDispatch();
this.manager = manager;
this.manager.eventBus = this.eventBus;
this.manager.cache(cache);
this.manager.consolidate(consolidate);
this.databaseConnector(db);
Expand Down Expand Up @@ -126,6 +131,12 @@ export class Coordinator {
if (arguments.length) {
this._logger = logger || voidLogger();
this.manager.logger(this._logger);

// subscribe logger to events

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good as a stepping stone but I think we can go ahead and make the logger a separate observer that users need to explicitly add. We can remove the logger entirely now imo.

this.eventBus.observe(EventType.QueryStart, (event) => this._logger.info('Query started:', event));
this.eventBus.observe(EventType.QueryEnd, (event) => this._logger.info('Query ended:', event));
this.eventBus.observe(EventType.ClientConnect, (event) => this._logger.info('Client connected:', event));
this.eventBus.observe(EventType.Error, (event) => this._logger.error('Error:', event.message));
}
return this._logger!;
}
Expand Down Expand Up @@ -249,9 +260,9 @@ export class Coordinator {
return client._pending = this.query(query, { priority })
.then(
data => client.queryResult(data).update(),
err => { this._logger?.error(err); client.queryError(err); }
err => { this.eventBus.emit(EventType.Error, { message: err }); client.queryError(err); }
)
.catch(err => this._logger?.error(err));
.catch(err => { this.eventBus.emit(EventType.Error, { message: err }); });
}

/**
Expand Down Expand Up @@ -280,6 +291,11 @@ export class Coordinator {
throw new Error('Client already connected.');
}

// emit ClientConnect
this.eventBus.emit(EventType.ClientConnect, {
// additional arguments for later -- for comprehensive client data
Comment thread
theVedanta marked this conversation as resolved.
Outdated
});

// add client to client set
clients?.add(client);

Expand Down Expand Up @@ -394,4 +410,4 @@ function updateSelection(
const query = info?.query(active.predicate) ?? client.query(filter);
return mc.updateClient(client, query);
}));
}
}
30 changes: 30 additions & 0 deletions packages/mosaic/core/src/Events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export enum EventType {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having this enum here. Wouldn't it be easier to have classes for the events that can be instantiated with a constructor?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is probably true. It will get rid of this "broken"-ish type interface for the events. But I remember that we agreed on enums (denoted by strings instead of numbers) to provide the user a simple list of event types in autocomplete

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we can still use enums in the event types but in order to create an event object, we could use a class. Maybe it's cleaner to actually put the event type into the message so that we can easily type check a message in isolation. Let's do that.

QueryStart = 'query-start',
QueryEnd = 'query-end',
ClientConnect = 'client-connect',
ClientStateChange = 'client-state-change',
Error = 'error'
}

export interface MosaicEvent {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be private/not exported?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we'll need this type when omitting pre-set keys in the coordinator/query-manager

timestamp: number;
// Extend later with more fields
Comment thread
domoritz marked this conversation as resolved.
Outdated
Comment thread
theVedanta marked this conversation as resolved.
Outdated
}

export interface QueryStartEvent extends MosaicEvent {
query: string;
materialized: boolean;
}

export interface QueryEndEvent extends MosaicEvent {
query: string;
materialized: boolean;
}

export interface ClientConnectEvent extends MosaicEvent {
clientId?: string;
}

export interface ErrorEvent extends MosaicEvent {
message: unknown;
Comment thread
domoritz marked this conversation as resolved.
Outdated
}
51 changes: 35 additions & 16 deletions packages/mosaic/core/src/QueryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { lruCache, voidCache } from './util/cache.js';
import { PriorityQueue } from './util/priority-queue.js';
import { QueryResult, QueryState } from './util/query-result.js';
import { voidLogger } from './util/void-logger.js';
import { EventType } from './Events.js';
import { ObserveDispatch } from './util/ObserveDispatch.js';

export const Priority = Object.freeze({ High: 0, Normal: 1, Low: 2 });

Expand All @@ -13,23 +15,23 @@ export class QueryManager {
private db: Connector | null;
private clientCache: Cache | null;
private _logger: Logger;
private _logQueries: boolean;
private _consolidate: ReturnType<typeof consolidator> | null;
/** Requests pending with the query manager. */
public pendingResults: QueryResult[];
private maxConcurrentRequests: number;
private pendingExec: boolean;
public eventBus?;

constructor(maxConcurrentRequests: number = 32) {
constructor(maxConcurrentRequests: number = 32, eventBus?: ObserveDispatch<unknown>) {
this.queue = new PriorityQueue(3);
this.db = null;
this.clientCache = null;
this._logger = voidLogger();
this._logQueries = false;
this._consolidate = null;
this.pendingResults = [];
this.maxConcurrentRequests = maxConcurrentRequests;
this.pendingExec = false;
this.eventBus = eventBus;
}

next(): void {
Expand Down Expand Up @@ -80,20 +82,36 @@ export class QueryManager {
const { query, type, cache = false, options } = request;
const sql = query ? `${query}` : null;

// emit QueryStart
// this `if` check is our version of the `logQueries` flag
if (this.eventBus) {
this.eventBus.emit(EventType.QueryStart, {
query: sql || '',
materialized: cache,
});
}

// check query cache
if (cache) {
const cached = this.clientCache!.get(sql!);
if (cached) {
const data = await cached;
this._logger.debug('Cache');
Comment thread
domoritz marked this conversation as resolved.
Outdated
result.ready(data);
// emit QueryEnd for cached
if (this.eventBus) {
Comment thread
domoritz marked this conversation as resolved.
Outdated
this.eventBus.emit(EventType.QueryEnd, {
query: sql || '',
materialized: cache,
});
}
return;
}
}

// issue query, potentially cache result
const t0 = performance.now();
if (this._logQueries) {
if (this.eventBus) {
this._logger.debug('Query', { type, sql, ...options });
}

Expand All @@ -107,7 +125,19 @@ export class QueryManager {

this._logger.debug(`Request: ${(performance.now() - t0).toFixed(1)}`);
result.ready(type === 'exec' ? null : data);

if (this.eventBus) {
Comment thread
domoritz marked this conversation as resolved.
Outdated
this.eventBus.emit(EventType.QueryEnd, {
query: sql || '',
Comment thread
domoritz marked this conversation as resolved.
Outdated
materialized: cache,
});
}
} catch (err) {
if (this.eventBus) {
Comment thread
domoritz marked this conversation as resolved.
Outdated
this.eventBus.emit(EventType.Error, {
message: err,
});
}
result.reject(err);
}
}
Expand Down Expand Up @@ -136,17 +166,6 @@ export class QueryManager {
return value ? (this._logger = value) : this._logger;
}

/**
* Get or set if queries should be logged.
* @param value Whether to log queries
* @returns Current logging state
*/
logQueries(): boolean;
logQueries(value: boolean): boolean;
logQueries(value?: boolean): boolean {
return value !== undefined ? this._logQueries = !!value : this._logQueries;
}

/**
* Get or set the database connector.
* @param connector Connector to set
Expand Down Expand Up @@ -217,4 +236,4 @@ export class QueryManager {
}
this.pendingResults = [];
}
}
}
Loading