From 21a268e9a34b110e8057709567d20755792e6517 Mon Sep 17 00:00:00 2001 From: stranger80 Date: Mon, 27 Feb 2023 22:46:47 +0100 Subject: [PATCH 1/4] GAP-29 WIP --- gaps/gap-29_service_api/gap-29_service_api.md | 35 ++++++++++++++++++ .../service_state_diagram.png | Bin 0 -> 32829 bytes 2 files changed, 35 insertions(+) create mode 100644 gaps/gap-29_service_api/gap-29_service_api.md create mode 100644 gaps/gap-29_service_api/service_state_diagram.png diff --git a/gaps/gap-29_service_api/gap-29_service_api.md b/gaps/gap-29_service_api/gap-29_service_api.md new file mode 100644 index 00000000..c7ab0011 --- /dev/null +++ b/gaps/gap-29_service_api/gap-29_service_api.md @@ -0,0 +1,35 @@ +--- +gap: GAP-29 +title: HL Service API +description: High level Requestor-side API concept for management of interactive services hosted on Golem Network. +author: stranger80 (@stranger80) +status: Draft +type: Feature +--- + +## Abstract +Abstract is a multi-sentence (short paragraph) technical summary. This should be a very terse and human-readable version of the specification section. Someone should be able to read only the abstract to get the gist of what this specification does. + +## Motivation +The motivation section should describe the "why" of this GAP. What problem does it solve? What benefit does it provide to the Golem ecosystem? What use cases does this GAP address? + +## Specification +The technical specification should describe the syntax and semantics of any new feature. + +## Rationale +The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work. + +## Backwards Compatibility +All GAPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The GAP **must** explain how the author proposes to deal with these incompatibilities. + +## Test Cases +Test cases are very useful in summarizing the scope and specifics of a GAP. If the test suite is too large to reasonably be included inline, then consider adding it as one or more files in `./gaps/gap-draft_title/` directory. + +## [Optional] Reference Implementation +An optional section that contains a reference/example implementation that people can use to assist in understanding or implementing this specification. If the implementation is too large to reasonably be included inline, then consider adding it as one or more files in `./gaps/gap-draft_title/`. + +## Security Considerations +All GAPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life cycle of the proposal. E.g. include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/gaps/gap-29_service_api/service_state_diagram.png b/gaps/gap-29_service_api/service_state_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..b752fd96af1d658e2233472c77208da0c97e8820 GIT binary patch literal 32829 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 Date: Tue, 28 Feb 2023 20:49:33 +0100 Subject: [PATCH 2/4] GAP-29 WIP --- gaps/gap-29_service_api/gap-29_service_api.md | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/gaps/gap-29_service_api/gap-29_service_api.md b/gaps/gap-29_service_api/gap-29_service_api.md index c7ab0011..056d7b42 100644 --- a/gaps/gap-29_service_api/gap-29_service_api.md +++ b/gaps/gap-29_service_api/gap-29_service_api.md @@ -8,28 +8,63 @@ type: Feature --- ## Abstract -Abstract is a multi-sentence (short paragraph) technical summary. This should be a very terse and human-readable version of the specification section. Someone should be able to read only the abstract to get the gist of what this specification does. +A generic high-level API is proposed to streamline writing Requestor Agent code to manage interactive services on Golem. The API includes a service development model based on an abstract service lifecycle, which is a scaffolding for management of service state via ExeScript commands. ## Motivation -The motivation section should describe the "why" of this GAP. What problem does it solve? What benefit does it provide to the Golem ecosystem? What use cases does this GAP address? +Golem allows for launching and control of interactive services. A service is, in general, a process which runs on a node controlled by a Provider, based on the Agreement with a Requestor, and responds to requests (passed either via Golem network, or totally outside of Golem network's visibility), until it is explicitly stopped (usually by a Requestor). + +The proposed service development model provides an abstraction layer over Golem Network mechanics which allows the developer to focus on service state transition logic - leaving the "logistics" of Provider and Agreement management to a high-level API library. ## Specification -The technical specification should describe the syntax and semantics of any new feature. +TODO The technical specification should describe the syntax and semantics of any new feature. + +### Service lifecycle + +```mermaid +sequenceDiagram + participant Golem as Engine + participant SampleService as Service + participant Agent as Requestor Agent App + + Agent ->>+ Golem: run_service(SampleService) + Golem ->> SampleService: init() + activate SampleService + Golem ->> SampleService: get_payload() + SampleService -->> Golem: payload + Golem ->> Golem: negotiate_agreement(payload) + Golem ->> SampleService: start() + SampleService -->> Golem: exe_script + Golem ->> SampleService: run() + SampleService -->> Golem: exe_script + Golem ->> SampleService: shutdown() + SampleService -->> Golem: exe_script + deactivate SampleService + + +``` + +### Starting logic + +### Running logic + +### Stopping logic + ## Rationale -The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work. +TODO The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work. ## Backwards Compatibility -All GAPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The GAP **must** explain how the author proposes to deal with these incompatibilities. +TODO All GAPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The GAP **must** explain how the author proposes to deal with these incompatibilities. ## Test Cases -Test cases are very useful in summarizing the scope and specifics of a GAP. If the test suite is too large to reasonably be included inline, then consider adding it as one or more files in `./gaps/gap-draft_title/` directory. +TODO +Include test cases with attach/detach (ie. Agent reconnecting and "joining the service management" in-flight) ## [Optional] Reference Implementation -An optional section that contains a reference/example implementation that people can use to assist in understanding or implementing this specification. If the implementation is too large to reasonably be included inline, then consider adding it as one or more files in `./gaps/gap-draft_title/`. +TODO ## Security Considerations -All GAPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life cycle of the proposal. E.g. include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. +TODO All GAPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life cycle of the proposal. E.g. include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file From a3cdabffa64fa4a29776f8b370f070b76a5ff5d6 Mon Sep 17 00:00:00 2001 From: stranger80 Date: Tue, 28 Feb 2023 21:38:53 +0100 Subject: [PATCH 3/4] GAP-29 WIP --- gaps/gap-29_service_api/gap-29_service_api.md | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/gaps/gap-29_service_api/gap-29_service_api.md b/gaps/gap-29_service_api/gap-29_service_api.md index 056d7b42..a0bf54c8 100644 --- a/gaps/gap-29_service_api/gap-29_service_api.md +++ b/gaps/gap-29_service_api/gap-29_service_api.md @@ -16,15 +16,44 @@ Golem allows for launching and control of interactive services. A service is, in The proposed service development model provides an abstraction layer over Golem Network mechanics which allows the developer to focus on service state transition logic - leaving the "logistics" of Provider and Agreement management to a high-level API library. ## Specification -TODO The technical specification should describe the syntax and semantics of any new feature. +This section summarizes the concept of Golem service execution model. ### Service lifecycle +A Service is an abstraction over an Activity launched on a Provider node. A Service follows a state transition sequence, as indicated on the following diagram. + +![Service lifecycle](service_state_diagram.png) + +### Service execution model + +To implement a Golem Service, a developer is expected to create a class containing code to provide: + +- specification of the Golem 'payload' that shall be launched on a Provider node +- logic (via a sequence of ExeScript commands) to be executed as the Service follows a transition of states in its lifecycle + +The initialization of the Service class and transition between states is controlled by the Golem Engine. + +```mermaid +--- +Service interface +--- +classDiagram + class Service{ + +get_payload() + +start() + +run() + +shutdown() + } +``` + +The execution sequence is indicated on the diagram below: ```mermaid sequenceDiagram - participant Golem as Engine - participant SampleService as Service participant Agent as Requestor Agent App + participant Golem as Engine + participant Agreement + participant Activity + participant SampleService as SampleService Agent ->>+ Golem: run_service(SampleService) Golem ->> SampleService: init() @@ -32,14 +61,29 @@ sequenceDiagram Golem ->> SampleService: get_payload() SampleService -->> Golem: payload Golem ->> Golem: negotiate_agreement(payload) + activate Agreement + Golem ->> Agreement: create_activity() + activate Activity + Golem ->> SampleService: start() SampleService -->> Golem: exe_script + Golem ->> Activity: exec(exe_script) + Golem ->> SampleService: run() SampleService -->> Golem: exe_script + Golem ->> Activity: exec(exe_script) + Golem ->> SampleService: shutdown() SampleService -->> Golem: exe_script + Golem ->> Activity: exec(exe_script) + + Golem ->> Activity: destroy_activity() + deactivate Activity + + Golem ->> Agreement: terminate_agreement() + deactivate Agreement + deactivate SampleService - ``` From 404c74727238c8c88067da2246e0871a5feebdce Mon Sep 17 00:00:00 2001 From: stranger80 Date: Tue, 28 Feb 2023 22:24:10 +0100 Subject: [PATCH 4/4] GAP-29 Draft --- gaps/gap-29_service_api/gap-29_service_api.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/gaps/gap-29_service_api/gap-29_service_api.md b/gaps/gap-29_service_api/gap-29_service_api.md index a0bf54c8..67c7924d 100644 --- a/gaps/gap-29_service_api/gap-29_service_api.md +++ b/gaps/gap-29_service_api/gap-29_service_api.md @@ -30,7 +30,9 @@ To implement a Golem Service, a developer is expected to create a class containi - specification of the Golem 'payload' that shall be launched on a Provider node - logic (via a sequence of ExeScript commands) to be executed as the Service follows a transition of states in its lifecycle -The initialization of the Service class and transition between states is controlled by the Golem Engine. +The execution of the service happens in the context of a `Golem` engine. The engine is a high-level API concept - an object which shields a developer from all the complex nuances of Golem's low-level APIs. All the market interaction, Agreement negotiation, Activity launch and ExeScript execution is encapsulated within the `Golem` engine object. + +In the Service API execution model the initialization of the Service class and transition between states is controlled by the `Golem` engine. The developer is expected to provide a definition of Service class implementation of following interface: ```mermaid --- @@ -45,19 +47,27 @@ classDiagram } ``` +Where: +- `get_payload()` - a method which returns a specification of a Golem 'payload' package (eg. indication of required runtime, VM image hash, specific Demand properties, etc.) +- `start()` - a "work generator" method which yields a sequence of ExeScript command batches to be executed on service start. Once the command sequence completes successfully - the service enters the `Running` state. +- `run()` - a "work generator" method which yields a sequence of ExeScript command batches to be executed while a service is running. Once the command sequence completes successfully - the service enters `Stopping` state, preparing for shutdown. +- `shutdown()` - a "work generator" method which yields a sequence of ExeScript command batches to be executed while a service is stopping. Once the command sequence completes successfully - the service terminates. + + The execution sequence is indicated on the diagram below: ```mermaid sequenceDiagram participant Agent as Requestor Agent App - participant Golem as Engine + participant Golem as Golem participant Agreement participant Activity participant SampleService as SampleService - Agent ->>+ Golem: run_service(SampleService) + Agent ->>+ Golem: run_service() Golem ->> SampleService: init() activate SampleService + Golem -->> Agent: SampleService Golem ->> SampleService: get_payload() SampleService -->> Golem: payload Golem ->> Golem: negotiate_agreement(payload) @@ -87,28 +97,18 @@ sequenceDiagram ``` -### Starting logic - -### Running logic - -### Stopping logic - - ## Rationale -TODO The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work. +The Service API is an attempt to provide a high-level abstraction over Golem entities, in a way that corresponds to the "twin" Task API. Therefore the Service object implementation follows the pattern of "work generator" - all "state transition" methods are expected to yield-return ExeScript to be executed within the Activity by the `Gelem` engine object. ## Backwards Compatibility -TODO All GAPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The GAP **must** explain how the author proposes to deal with these incompatibilities. +The Service API is a high-level layer over the Golem daemon and REST APIs. Its introduction does not break any compatibility dependencies. ## Test Cases TODO Include test cases with attach/detach (ie. Agent reconnecting and "joining the service management" in-flight) -## [Optional] Reference Implementation -TODO - ## Security Considerations -TODO All GAPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life cycle of the proposal. E.g. include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. +The Service API does not include any security-related features. It must comply with any security mechanisms implied by lower levels of Golem stack. ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file