-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[data.search] Server-side background session service #81099
Conversation
Co-authored-by: Anton Dosov <dosantappdev@gmail.com>
* under the License. | ||
*/ | ||
|
||
import { createHash } from 'crypto'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems there is already a trimmed down version of exactly what we need in core: src/core/public/utils/crypto/sha256.ts
Since this code is in /common
and has a risk of getting into UI, should we consider using a trimmed down version from core
now?
(Small caveat is that we will need to move that util to common
first: src/core/public/utils/crypto/sha256.ts
-> src/core/common/utils/crypto/sha256.ts
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Using it in #83073 and in general seem to be working well.
Some remarks, don't think we need to fix it in this pr as can be done in parallel and unblock client side reviews:
- Client side session service will be improved. (observables, missing methods, types, etc..)
- In some places error handling needs to be improved. I often noticed "500 Internal service error" while testing. For example, when trying to restore searches and hash mismatches
- Bumped couple times into race condition:
ResponseError: [background-session:63112a17-1f82-4711-ab7d-6b2d2e974ae4]: version conflict, required seqNo [379], primary term [1]. current document has seqNo [380] and primary term [1]: version_conflict_engine_exception
. I think this is happening when you get back to inactive tab. - Multi-tenant Kibana use-case
- For some reason kibana complained about missing
userId
in background search SO mapping. Maybe I had some stale data?
} | ||
|
||
public delete(sessionId: string) { | ||
return this.http!.delete(`/internal/session/${encodeURIComponent(sessionId)}}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return this.http!.delete(`/internal/session/${encodeURIComponent(sessionId)}}`); | |
return this.http!.delete(`/internal/session/${encodeURIComponent(sessionId)}`); |
} | ||
|
||
public update(sessionId: string, attributes: Partial<BackgroundSessionSavedObjectAttributes>) { | ||
return this.http!.put(`/internal/session/${encodeURIComponent(sessionId)}}`, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return this.http!.put(`/internal/session/${encodeURIComponent(sessionId)}}`, { | |
return this.http!.put(`/internal/session/${encodeURIComponent(sessionId)}`, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch
} | ||
|
||
public get(sessionId: string) { | ||
return this.http!.get(`/internal/session/${encodeURIComponent(sessionId)}}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return this.http!.get(`/internal/session/${encodeURIComponent(sessionId)}}`); | |
return this.http!.get(`/internal/session/${encodeURIComponent(sessionId)}`); |
update: ( | ||
sessionId: string, | ||
attributes: Partial<BackgroundSessionSavedObjectAttributes> | ||
) => Promise<any>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would would be the proper return types for this CRUD methods?
I can add in follow up client side PR, just not sure what are those.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an intermediate review, Ill add some more after testing
|
||
export interface BackgroundSessionSavedObjectAttributes { | ||
name: string; | ||
url: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thing we shouldn't have a URL, but an app name and two sets of parameters generated using the URL Generator (original and restore URLs)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you okay with leaving this to the PR that integrates with the URL generator? If you prefer, I can leave out the url
portion altogether from this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets leave it out then
} | ||
|
||
public clear() { | ||
this._isStored = false; | ||
this._isRestore = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you set this to true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be false, not sure how that got through
@@ -30,6 +34,18 @@ export class SessionService implements ISessionService { | |||
} | |||
private appChangeSubscription$?: Subscription; | |||
private curApp?: string; | |||
private http?: HttpStart; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe instead define private http!: HttpStart;
and then we won't have to check all the time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't even know that was a thing
name: { | ||
type: 'keyword', | ||
}, | ||
url: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I'd add a creation time, or all SOs have one?
- We need the
appId
, and two sets of URL params (restore and original) - I think we also should save the status (we want to filter by it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SOs will have updated_at
but I'm not seeing a creation time. I'll add that and the status
} | ||
); | ||
|
||
router.post( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// nit
Why use POST for find?
Sounds like a classic GET to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's what I thought initially too, but we need to send the FindOptions
. I guess we could send them in as query parameters instead of inside the body. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd just do the same thing that core
does with their client
body: response, | ||
}); | ||
} catch (err) { | ||
return res.customError({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could get a util for the error format? I see this block everywhere (npt necessarily in this PR)
body: schema.object( | ||
{ | ||
sessionId: schema.maybe(schema.string()), | ||
isStored: schema.maybe(schema.boolean()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use a schema.conditional
here?
@@ -57,6 +57,7 @@ export const enhancedEsSearchStrategyProvider = ( | |||
utils.toSnakeCase({ | |||
...(await getDefaultSearchParams(uiSettingsClient)), | |||
batchedReduceSize: 64, | |||
keepOnCompletion: true, // Always return an ID, even if the request completes quickly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did we add this? Sounds like a serious overhead to the system, that applies even if we dont save a single session
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to ensure that all requests generate IDs and return them. Otherwise, how will we get back the original data when the session is restored?
Yeah, that is probably the case. I removed it for now and will re-add in a follow-up PR. |
@elasticmachine merge upstream |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a few more comments
Overall LGTM
*/ | ||
|
||
export enum BackgroundSessionStatus { | ||
INCOMPLETE = 'incomplete', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//nit IN_PROGRESS?
/** | ||
* Deletes a session | ||
*/ | ||
delete: (sessionId: string) => Promise<any>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returns Promise<boolean>
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, probably Promise<void>
since an unsuccessful delete
will throw.
|
||
export interface BackgroundSessionSavedObjectAttributes { | ||
name: string; | ||
url: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets leave it out then
sessionId: string, | ||
name: string, | ||
url: string, | ||
expires: Date = new Date(Date.now() + DEFAULT_EXPIRATION), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm not mistaken, the actual expiration is returned with each async search response, maybe we could use that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There could be multiple requests/responses for a single session. What we should actually probably be doing here is actually calling the extend
function (when it is implemented) to set the expires
in each search to this value, rather than the other way around. Thoughts?
return session; | ||
}; | ||
|
||
// TODO: Throw an error if this session doesn't belong to this user |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't savedObjectClient already do that, as it's scoped?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If two users are in the same space, they can read/write each other's objects without errors, which is expected. Here we need to enforce that even if a user is in the same space, they can't access another user's session.
💚 Build SucceededMetrics [docs]Module Count
Distributable file count
Page load bundle
Saved Objects .kibana field count
History
To update your PR or re-run it, just comment with: |
* [Search] Add request context and asScoped pattern * Update docs * Unify interface for getting search client * [WIP] [data.search] Server-side background session service * Update examples/search_examples/server/my_strategy.ts Co-authored-by: Anton Dosov <dosantappdev@gmail.com> * Review feedback * Fix checks * Add tapFirst and additional props for session * Fix CI * Fix security search * Fix test * Fix test for reals * Add restore method * Add code to search examples * Add restore and search using restored ID * Fix handling of preference and order of params * Trim & cleanup * Fix types * Review feedback * Add tests and remove handling of username * Update docs * Move utils to server * Review feedback * More review feedback * Regenerate docs * Review feedback * Doc changes Co-authored-by: Anton Dosov <dosantappdev@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
* master: (60 commits) Forward any registry cache-control header for files (elastic#83680) Revert "[Alerting] Add `alert.updatedAt` field to represent date of last user edit (elastic#83578)" [Security Solution][Detections] Fix adding an action to detection rules (elastic#83722) Make expectSnapshot available in all functional test runs (elastic#82932) Skip failing cypress test Increase bulk request timeout during esArchiver load (elastic#83657) [data.search] Server-side background session service (elastic#81099) [maps] convert VectorStyleEditor to TS (elastic#83582) Revert "[App Search] Engine overview layout stub (elastic#83504)" Adding documentation for global action configuration options (elastic#83557) [Metrics UI] Optimizations for Snapshot and Inventory Metadata (elastic#83596) chore(NA): update lmdb store to v0.8.15 (elastic#83726) [App Search] Engine overview layout stub (elastic#83504) [Workplace Search] Update SourceIcon to match latest changes in ent-search (elastic#83714) [Enterprise Search] Rename React Router helpers (elastic#83718) [Maps] Add 'crossed' & 'exited' events to tracking alert (elastic#82463) Updating code-owners to use new core/app-services team names (elastic#83731) Add Managed label to data streams and a view switch for the table (elastic#83049) [Maps] Add query bar inputs to geo threshold alerts tracked points & boundaries (elastic#80871) fix(NA): search examples kibana version declaration (elastic#83182) ...
* master: (60 commits) Forward any registry cache-control header for files (elastic#83680) Revert "[Alerting] Add `alert.updatedAt` field to represent date of last user edit (elastic#83578)" [Security Solution][Detections] Fix adding an action to detection rules (elastic#83722) Make expectSnapshot available in all functional test runs (elastic#82932) Skip failing cypress test Increase bulk request timeout during esArchiver load (elastic#83657) [data.search] Server-side background session service (elastic#81099) [maps] convert VectorStyleEditor to TS (elastic#83582) Revert "[App Search] Engine overview layout stub (elastic#83504)" Adding documentation for global action configuration options (elastic#83557) [Metrics UI] Optimizations for Snapshot and Inventory Metadata (elastic#83596) chore(NA): update lmdb store to v0.8.15 (elastic#83726) [App Search] Engine overview layout stub (elastic#83504) [Workplace Search] Update SourceIcon to match latest changes in ent-search (elastic#83714) [Enterprise Search] Rename React Router helpers (elastic#83718) [Maps] Add 'crossed' & 'exited' events to tracking alert (elastic#82463) Updating code-owners to use new core/app-services team names (elastic#83731) Add Managed label to data streams and a view switch for the table (elastic#83049) [Maps] Add query bar inputs to geo threshold alerts tracked points & boundaries (elastic#80871) fix(NA): search examples kibana version declaration (elastic#83182) ...
…ode-details * 'master' of github.com:elastic/kibana: fixed pagination in connectors list (elastic#83638) Forward any registry cache-control header for files (elastic#83680) Revert "[Alerting] Add `alert.updatedAt` field to represent date of last user edit (elastic#83578)" [Security Solution][Detections] Fix adding an action to detection rules (elastic#83722) Make expectSnapshot available in all functional test runs (elastic#82932) Skip failing cypress test Increase bulk request timeout during esArchiver load (elastic#83657) [data.search] Server-side background session service (elastic#81099) [maps] convert VectorStyleEditor to TS (elastic#83582) Revert "[App Search] Engine overview layout stub (elastic#83504)" Adding documentation for global action configuration options (elastic#83557) [Metrics UI] Optimizations for Snapshot and Inventory Metadata (elastic#83596) chore(NA): update lmdb store to v0.8.15 (elastic#83726) [App Search] Engine overview layout stub (elastic#83504) [Workplace Search] Update SourceIcon to match latest changes in ent-search (elastic#83714) [Enterprise Search] Rename React Router helpers (elastic#83718)
* [Search] Add request context and asScoped pattern * Update docs * Unify interface for getting search client * [WIP] [data.search] Server-side background session service * Update examples/search_examples/server/my_strategy.ts Co-authored-by: Anton Dosov <dosantappdev@gmail.com> * Review feedback * Fix checks * Add tapFirst and additional props for session * Fix CI * Fix security search * Fix test * Fix test for reals * Add restore method * Add code to search examples * Add restore and search using restored ID * Fix handling of preference and order of params * Trim & cleanup * Fix types * Review feedback * Add tests and remove handling of username * Update docs * Move utils to server * Review feedback * More review feedback * Regenerate docs * Review feedback * Doc changes Co-authored-by: Anton Dosov <dosantappdev@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Anton Dosov <dosantappdev@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
* [Search] Add request context and asScoped pattern * Update docs * Unify interface for getting search client * [WIP] [data.search] Server-side background session service * Update examples/search_examples/server/my_strategy.ts Co-authored-by: Anton Dosov <dosantappdev@gmail.com> * Review feedback * Fix checks * Add tapFirst and additional props for session * Fix CI * Fix security search * Fix test * Fix test for reals * Add restore method * Add code to search examples * Add restore and search using restored ID * Fix handling of preference and order of params * Trim & cleanup * Fix types * Review feedback * Add tests and remove handling of username * Update docs * Move utils to server * Review feedback * More review feedback * Regenerate docs * Review feedback * Doc changes Co-authored-by: Anton Dosov <dosantappdev@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Summary
Adds the server-side background session service, allowing background search sessions to be created, deleted, listed, and restored. It also adds support to the client-side session service for accessing these methods.
The basic flow is as follows:
(See the search example plugin for an example of how to use.)
Checklist
Delete any items that are not applicable to this PR.
For maintainers