Skip to content
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

feat: initial work on embedded dispatch #838

Merged
merged 18 commits into from
May 7, 2024
Merged

Conversation

darvld
Copy link
Member

@darvld darvld commented Apr 29, 2024

Ready for review Powered by Pull Request Badge

Summary

This PR adds initial work on the Elide Embedded module, which allows native
applications to embed the Elide runtime as a shared library. The embedded
runtime is designed to act as a hosting engine, providing request dispatch
and guest app management capabilities.

Native API

A basic C API is exposed to allow host applications to manage the runtime via
GraalVM. Additional types are defined in elide_embedded_types.h.

Runtime Lifecycle

Host applications are expected to make use of a single runtime instance for all
operations. The runtime itself is thread-safe and can handle concurrent calls
to any of the exposed functions.

The first step is to initialize the runtime, passing a configuration struct to
indicate the desired settings for the instance.

Note that all functions in the API require the host to pass a
graal_isolate_t pointer as first argument. This is a current limitation of
the GraalVM Native C API.

int main() {
    // create the GraalVM isolate used by the runtime
    graal_isolatethread_t *thread = NULL;
    if (graal_create_isolate(NULL, NULL, &thread) != 0) {
        fprintf(stderr, "error on isolate creation or attach\n");
        return 1;
    }

    // prepare the runtime configuration
    elide_config_t config = {
        /* version = */ V1_0,
        /* format = */ PROTOBUF,
        /* guest_root = */ "/workspace/elide/hosted",
        /* languages = */ 1,
    };

    // initialize the runtime
    if (elide_embedded_init(&thread, &config) != 0) {
        fprintf(stderr, "error on runtime initialization\n");
        return 1;
    }

    return 0;
}

After initialization, guest applications can be registered and managed, but
request processing will not be available until the runtime is started.

if (elide_embedded_start(&thread) != 0) {
    fprintf(stderr, "error on runtime start\n");
    return 1;
}

Guest Applications

A guest application is a self-contained unit capable of processing requests
using code written in a language supported by Elide. Applications are added
to the runtime and provide a scope for request dispatch.

// prepare the configuration for the app
elide_app_config_t app_config = {
    /* id = */ "sample-app",
    /* entrypoint = */ "index.js",
    /* language = */ JS,
    /* mode = */ FETCH,
};

// register the app with the runtime
elide_app_t *app = NULL;
if (elide_app_create(&thread, &app_config, &elide_app_t) != 0) {
    fprintf(stderr, "error on app creation\n");
    return 1;
}

// we can now start the app to allow it to process requests
if (elide_app_start(&thread, &elide_app_t) != 0) {
    fprintf(stderr, "error on app startup\n");
    return 1;
}

Internally, each guest application is launched as a Kotlin CoroutineScope,
and requests are dispatched as coroutines. This allows structured concurrency
rules to handle operations such as application shutdown or cordoning.

Tests

There are two main test suites for the embedded runtime:

  • The base JVM implementation of the runtime is tested as-is, assuming a JVM
    host, and have no knowledge of native features.
  • The native shared library is tested using Panama to interact with the
    generated binary, this allow coverage of the actual distribution.

Upcoming work

The features introduced by this PR are the foundation of the future embedded
module. Request dispatch is not currently implemented in full as it requires
guest language intrinsics that are yet to be designed.

The goal of this PR is to establish the main native API by which host apps can
interact with Elide, and serve as a proof of concept for native embeddings of
the runtime.

@darvld darvld added feature Large PRs or issues with full-blown features 🚧 WIP Works-in-progress. Blocks merge 🧪 labs Experimental work labels Apr 29, 2024
@darvld darvld self-assigned this Apr 29, 2024
Copy link

coderabbitai bot commented Apr 29, 2024

Walkthrough

Walkthrough

The recent updates encompass a holistic refinement of the Elide Embedded system, spanning documentation enhancements, native interoperability classes introduction, Kotlin implementation advancements, dispatcher optimizations, and robust testing mechanisms. These changes collectively elevate the system's functionality and performance.

Changes

Files/Classes Change Summary
elide.embedded, elide.embedded.http Refined documentation and package organization for improved public API interactions.
elide.embedded.interop... Introduced classes for native interoperability, enhancing protocol handling capabilities.
ElideEmbedded.kt, EmbeddedApp.kt... Updated and added Kotlin files to bolster advanced lifecycle and dispatch management.
EmbeddedDispatcherImpl.kt, MicronautRuntime... Implemented new dispatcher and DI container functionalities, along with build-time feature registration.
NativeInterop.kt, elide_embedded_types.h... Enhanced native interoperability features and testing mechanisms, with updates to native library handling.
native-image.properties Updated properties to leverage the new EmbeddedFeature for streamlined build-time registration.

🐇✨
A hop of joy, a skip of glee,
New changes bloom, fresh as can be.
Code weaves like threads in a tapestry,
In Elide's world, where all agree.
Cheers to the team, from me, 🐰!


Recent Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between bd9f5ae and a4d1d4b.
Files ignored due to path filters (11)
  • packages/embedded/detekt-baseline.xml is excluded by !**/*.xml
  • packages/embedded/src/main/resources/META-INF/native-image/jni-config.json is excluded by !**/*.json
  • packages/embedded/src/main/resources/META-INF/native-image/predefined-classes-config.json is excluded by !**/*.json
  • packages/embedded/src/main/resources/META-INF/native-image/proxy-config.json is excluded by !**/*.json
  • packages/embedded/src/main/resources/META-INF/native-image/reflect-config.json is excluded by !**/*.json
  • packages/embedded/src/main/resources/META-INF/native-image/resource-config.json is excluded by !**/*.json
  • packages/embedded/src/main/resources/META-INF/native-image/serialization-config.json is excluded by !**/*.json
  • packages/embedded/src/main/resources/application.yml is excluded by !**/*.yml
  • packages/embedded/src/main/resources/bootstrap.yml is excluded by !**/*.yml
  • packages/embedded/src/main/resources/logback.xml is excluded by !**/*.xml
  • packages/embedded/src/test/resources/logback-test.xml is excluded by !**/*.xml
Files selected for processing (43)
  • packages/embedded/build.gradle.kts (1 hunks)
  • packages/embedded/module.md (3 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/ElideEmbeddedNative.java (1 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/ElideNativeDirectives.java (1 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/NativeAppCallback.java (1 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/NativeAppCallbackHolder.java (1 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/NativeAppConfig.java (1 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/NativeAppLanguage.java (1 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/NativeAppMode.java (1 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/NativeEmbeddedConfig.java (1 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/NativeProtocolFormat.java (1 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/NativeProtocolVersion.java (1 hunks)
  • packages/embedded/src/main/java/elide/embedded/interop/NativeResultCodes.java (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/ElideEmbedded.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedApp.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedAppRegistry.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedCall.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedCallCodec.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedCallDispatcher.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedConfiguration.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedGuestLanguage.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedProtocolFormat.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedProtocolVersion.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedRuntimeContext.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/http/EmbeddedRequest.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/http/EmbeddedResponse.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/internal/AppEntrypoint.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/internal/EmbeddedAppImpl.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/internal/EmbeddedAppRegistryImpl.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/internal/EmbeddedCallImpl.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/internal/EmbeddedDispatcherImpl.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/internal/EmbeddedFeature.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/internal/MicronautRuntimeContext.kt (1 hunks)
  • packages/embedded/src/main/kotlin/elide/embedded/interop/NativeInterop.kt (1 hunks)
  • packages/embedded/src/main/native/elide_embedded_types.h (1 hunks)
  • packages/embedded/src/main/resources/META-INF/native-image/native-image.properties (1 hunks)
  • packages/embedded/src/test/kotlin/elide/embedded/EmbeddedAppTest.kt (1 hunks)
  • packages/embedded/src/test/kotlin/elide/embedded/EmbeddedRuntimeTest.kt (1 hunks)
  • packages/embedded/src/test/kotlin/elide/embedded/NativeEmbeddedRuntimeTest.kt (1 hunks)
  • packages/embedded/src/test/kotlin/elide/embedded/native/ElideNativeLibrary.kt (1 hunks)
  • packages/embedded/src/test/kotlin/elide/embedded/native/NativeCallbackAdapter.kt (1 hunks)
  • packages/embedded/src/test/kotlin/elide/embedded/native/NativeExtensions.kt (1 hunks)
  • packages/embedded/src/test/kotlin/elide/embedded/native/NativeLibrary.kt (1 hunks)
Files not summarized due to errors (1)
  • packages/embedded/build.gradle.kts: Error: Message exceeds token limit
Files skipped from review due to trivial changes (1)
  • packages/embedded/src/main/java/elide/embedded/interop/NativeResultCodes.java
Files skipped from review as they are similar to previous changes (38)
  • packages/embedded/src/main/java/elide/embedded/interop/ElideNativeDirectives.java
  • packages/embedded/src/main/java/elide/embedded/interop/NativeAppCallback.java
  • packages/embedded/src/main/java/elide/embedded/interop/NativeAppCallbackHolder.java
  • packages/embedded/src/main/java/elide/embedded/interop/NativeAppConfig.java
  • packages/embedded/src/main/java/elide/embedded/interop/NativeAppLanguage.java
  • packages/embedded/src/main/java/elide/embedded/interop/NativeAppMode.java
  • packages/embedded/src/main/java/elide/embedded/interop/NativeEmbeddedConfig.java
  • packages/embedded/src/main/java/elide/embedded/interop/NativeProtocolFormat.java
  • packages/embedded/src/main/java/elide/embedded/interop/NativeProtocolVersion.java
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedApp.kt
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedAppRegistry.kt
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedCall.kt
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedCallCodec.kt
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedCallDispatcher.kt
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedConfiguration.kt
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedGuestLanguage.kt
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedProtocolFormat.kt
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedProtocolVersion.kt
  • packages/embedded/src/main/kotlin/elide/embedded/EmbeddedRuntimeContext.kt
  • packages/embedded/src/main/kotlin/elide/embedded/http/EmbeddedRequest.kt
  • packages/embedded/src/main/kotlin/elide/embedded/http/EmbeddedResponse.kt
  • packages/embedded/src/main/kotlin/elide/embedded/internal/AppEntrypoint.kt
  • packages/embedded/src/main/kotlin/elide/embedded/internal/EmbeddedAppImpl.kt
  • packages/embedded/src/main/kotlin/elide/embedded/internal/EmbeddedAppRegistryImpl.kt
  • packages/embedded/src/main/kotlin/elide/embedded/internal/EmbeddedCallImpl.kt
  • packages/embedded/src/main/kotlin/elide/embedded/internal/EmbeddedDispatcherImpl.kt
  • packages/embedded/src/main/kotlin/elide/embedded/internal/EmbeddedFeature.kt
  • packages/embedded/src/main/kotlin/elide/embedded/internal/MicronautRuntimeContext.kt
  • packages/embedded/src/main/kotlin/elide/embedded/interop/NativeInterop.kt
  • packages/embedded/src/main/native/elide_embedded_types.h
  • packages/embedded/src/main/resources/META-INF/native-image/native-image.properties
  • packages/embedded/src/test/kotlin/elide/embedded/EmbeddedAppTest.kt
  • packages/embedded/src/test/kotlin/elide/embedded/EmbeddedRuntimeTest.kt
  • packages/embedded/src/test/kotlin/elide/embedded/NativeEmbeddedRuntimeTest.kt
  • packages/embedded/src/test/kotlin/elide/embedded/native/ElideNativeLibrary.kt
  • packages/embedded/src/test/kotlin/elide/embedded/native/NativeCallbackAdapter.kt
  • packages/embedded/src/test/kotlin/elide/embedded/native/NativeExtensions.kt
  • packages/embedded/src/test/kotlin/elide/embedded/native/NativeLibrary.kt
Additional Context Used
LanguageTool (6)
packages/embedded/module.md (6)

Near line 3: This sentence does not start with an uppercase letter.
Context: # Module embedded elide-embedded implements native embedded dispatch of Elide appli...


Near line 7: Possible spelling mistake found.
Context: ... meant to be implemented from within a GraalVM native image...


Near line 45: If a new sentence starts here, add a space and start with an uppercase letter.
Context: ...tId> ``` # Package elide.embedded Public API used to interact with the e...


Near line 48: Possible spelling mistake found.
Context: ...nd are meant to be accessed only by the ElideEmbedded class, as a singleton representing a r...


Near line 51: Possible spelling mistake found.
Context: ...ime instance. # Package elide.embedded.http Public types used during dispatch, as ...


Near line 53: Possible missing comma found.
Context: ... # Package elide.embedded.http Public types used during dispatch, as a bridge betwe...


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

socket-security bot commented Apr 29, 2024

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher

🚮 Removed packages: npm/lz-string@1.5.0

View full report↗︎

@darvld darvld force-pushed the feat/embedded-dispatch branch 3 times, most recently from 9560132 to 573dc3a Compare April 30, 2024 01:11
Copy link

codecov bot commented Apr 30, 2024

Codecov Report

Attention: Patch coverage is 26.18297% with 234 lines in your changes are missing coverage. Please review.

Project coverage is 35.83%. Comparing base (bd9f5ae) to head (a4d1d4b).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #838      +/-   ##
==========================================
- Coverage   36.12%   35.83%   -0.30%     
==========================================
  Files         506      501       -5     
  Lines       16117    15868     -249     
  Branches     2140     2132       -8     
==========================================
- Hits         5823     5686     -137     
+ Misses       9894     9791     -103     
+ Partials      400      391       -9     
Flag Coverage Δ
gradle 35.83% <26.18%> (-0.30%) ⬇️
jvm 35.83% <26.18%> (-0.30%) ⬇️
lib 35.83% <26.18%> (-0.30%) ⬇️
plugin 35.83% <26.18%> (-0.30%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
...ain/kotlin/elide/embedded/EmbeddedConfiguration.kt 100.00% <100.00%> (ø)
...ain/kotlin/elide/embedded/EmbeddedGuestLanguage.kt 100.00% <100.00%> (ø)
...in/kotlin/elide/embedded/EmbeddedProtocolFormat.kt 100.00% <100.00%> (ø)
...n/kotlin/elide/embedded/EmbeddedProtocolVersion.kt 100.00% <100.00%> (ø)
...dded/src/main/kotlin/elide/embedded/EmbeddedApp.kt 93.33% <93.33%> (ø)
...elide/embedded/internal/MicronautRuntimeContext.kt 93.75% <93.75%> (ø)
.../elide/embedded/interop/ElideNativeDirectives.java 0.00% <0.00%> (ø)
...ain/java/elide/embedded/interop/NativeAppMode.java 0.00% <0.00%> (ø)
.../elide/embedded/interop/NativeProtocolVersion.java 0.00% <0.00%> (ø)
...ded/src/main/kotlin/elide/embedded/EmbeddedCall.kt 0.00% <0.00%> (ø)
... and 12 more

... and 4 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update bd9f5ae...a4d1d4b. Read the comment docs.

@darvld darvld marked this pull request as ready for review May 3, 2024 23:08
@darvld darvld requested a review from sgammon as a code owner May 3, 2024 23:08
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 20

Out of diff range and nitpick comments (2)
packages/embedded/module.md (1)

Line range hint 1-1: Capitalize the first letter of the document title to maintain consistency and formality in documentation.

-# Module embedded
+# Module Embedded
packages/embedded/build.gradle.kts (1)

13-13: Clarify the purpose of configuration properties.

Consider adding comments to explain the purpose of the nativeTest property and how it affects the build process. This will help other developers understand the significance of this configuration.

Copy link
Member

@sgammon sgammon left a comment

Choose a reason for hiding this comment

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

overall great, just some basic questions

darvld added 16 commits May 3, 2024 19:41
- simplified core api.
- micronaut di container.
- improved testing.
- run native interop tests conditionally.
- add JVM runtime tests.
- adjust verbosity of Micronaut loggers for tests.
- app implementation.
- native API for embedded apps.
- observable app lifecycle methods.

Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>

wip(embedded): native callbacks for app lifecycle methods.
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
- initial dispatcher implementation.
- improved runtime interop.

Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
darvld added 2 commits May 3, 2024 19:41
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
Signed-off-by: Dario Valdespino <dvaldespino00@gmail.com>
@sgammon sgammon removed the 🚧 WIP Works-in-progress. Blocks merge label May 7, 2024
@sgammon sgammon merged commit abbe5c3 into main May 7, 2024
22 checks passed
@sgammon sgammon deleted the feat/embedded-dispatch branch May 7, 2024 17:53
@sgammon sgammon mentioned this pull request May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Large PRs or issues with full-blown features 🧪 labs Experimental work
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants