Skip to content
This repository has been archived by the owner on Mar 11, 2022. It is now read-only.

Flexible responses #47

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ venv
*.iml
protobuf/frontend
protobuf/protocol
protobuf/example/shoppingcart
protobuf/example/shoppingcart
akkaserverless/akkaserverless
akkaserverless/google
10 changes: 10 additions & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Contributors

## Special thanks for all the people who had helped this project so far:
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for keeping a Contributors list while migrating this to AS.


* [sleipnir](https://github.com/sleipnir) (Creator)
* [marcellanz](https://github.com/marcellanz) (Creator)
* [chomnoue](https://github.com/chomnoue) (Creator)
* [pvlugter](https://github.com/pvlugter) (Creator)
* [GratefulTony](https://github.com/GratefulTony) (Creator)
* [jpollock](https://github.com/jpollock) (Akka Serverless Migrator)
68 changes: 30 additions & 38 deletions Description.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,21 @@
Akka Serverless makes development and operation of high-performing stateful services enjoyable: it provides SDKs for building services, and a managed cloud platform for deploying them. The SDKs expose a simple programming model, available in popular programming languages, that eliminates the need for plumbing code to handle database access or connections. The managed platform relieves you from configuring and maintaining the orchestration platform, and the data stores. Akka Serverless auto-scales services, and handles network partitions and failures. It also gives clear visibility into the running system with unified and scalable logging and monitoring.

Cloudstate is a specification, protocol, and reference implementation for providing distributed state management patterns suitable for **Serverless** computing.
The current supported and envisioned patterns include:
Read more [here](https://developer.lightbend.com/docs/akka-serverless/index.html) and sign-up [here](https://console.akkaserverless.com/p/register#) for a free account.

* **Event Sourcing**
* **Conflict-Free Replicated Data Types (CRDTs)**
* **Key-Value storage**
* **P2P messaging**
* **CQRS read side projections**
The Akka Serverless Python user language support is a library that implements the Akka Serverless protocol and offers an pythonistic API
Copy link
Contributor

@marcellanz marcellanz Aug 30, 2021

Choose a reason for hiding this comment

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

Suggested change
The Akka Serverless Python user language support is a library that implements the Akka Serverless protocol and offers an pythonistic API
The Akka Serverless Python SDK is a library that implements the Akka Serverless protocol and offers a pythonistic API

User Language Support Library is old Cloudstate speak I think.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, Akka Serverless is using SDK.

for writing components that implement the types supported by the Akka Serverless protocol. It is a [Tier 3 SDK](https://developer.lightbend.com/docs/akka-serverless/reference/service-api-reference.html).

Cloudstate is polyglot, which means that services can be written in any language that supports gRPC,
and with language specific libraries provided that allow idiomatic use of the patterns in each language.
Cloudstate can be used either by itself, in combination with a Service Mesh,
or it is envisioned that it will be integrated with other Serverless technologies such as [Knative](https://knative.dev/).

Read more about the design, architecture, techniques, and technologies behind Cloudstate in [this section in the documentation](https://github.com/cloudstateio/cloudstate/blob/master/README.md#enter-cloudstate).

The Cloudstate Python user language support is a library that implements the Cloudstate protocol and offers an pythonistic API
for writing entities that implement the types supported by the Cloudstate protocol.

The Cloudstate documentation can be found [here](https://cloudstate.io/docs/)
The Akka Serverless documentation can be found [here](https://developer.lightbend.com/docs/akka-serverless/index.html)

## Install and update using pip:

```
pip install -U cloudstate
pip install -U akkaserverless
```
## Use Starter App

Visit https://github.com/jpollock/akka-serverless-starter-python to use that repository as a template. Simply click "Use this template". (Explanation for the process, general to Github, is [here](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/creating-a-repository-from-a-template)).


## A Simple EventSourced Example:

Expand All @@ -35,26 +26,26 @@ pip install -U cloudstate
syntax = "proto3";

import "google/protobuf/empty.proto";
import "cloudstate/entity_key.proto";
import "akkaserverless/annotations.proto";
import "google/api/annotations.proto";
import "google/api/http.proto";

package com.example.shoppingcart;

message AddLineItem {
string user_id = 1 [(.cloudstate.entity_key) = true];
string user_id = 1 [(akkaserverless.field).entity_key = true];
string product_id = 2;
string name = 3;
int32 quantity = 4;
}

message RemoveLineItem {
string user_id = 1 [(.cloudstate.entity_key) = true];
string user_id = 1 [(akkaserverless.field).entity_key = true];
string product_id = 2;
}

message GetShoppingCart {
string user_id = 1 [(.cloudstate.entity_key) = true];
string user_id = 1 [(akkaserverless.field).entity_key = true];
}

message LineItem {
Expand Down Expand Up @@ -102,16 +93,16 @@ Here is an example of how to compile the sample proto file:
python -m grpc_tools.protoc -I../../protos --python_out=. --grpc_python_out=. ../../protos/shoppingcart.proto
```

### 3. Implement your business logic under an EventSourced Cloudstate Entity
### 3. Implement your business logic under an EventSourced Akka Serverless Entity

```
from dataclasses import dataclass, field
from typing import MutableMapping

from google.protobuf.empty_pb2 import Empty

from cloudstate.event_sourced_context import EventSourcedCommandContext
from cloudstate.event_sourced_entity import EventSourcedEntity
from akkaserverless.event_sourced_context import EventSourcedCommandContext
from akkaserverless.event_sourced_entity import EventSourcedEntity
from shoppingcart.domain_pb2 import (Cart as DomainCart, LineItem as DomainLineItem, ItemAdded, ItemRemoved)
from shoppingcart.shoppingcart_pb2 import (Cart, LineItem, AddLineItem, RemoveLineItem)
from shoppingcart.shoppingcart_pb2 import (_SHOPPINGCART, DESCRIPTOR as FILE_DESCRIPTOR)
Expand All @@ -127,7 +118,7 @@ def init(entity_id: str) -> ShoppingCartState:
return ShoppingCartState(entity_id)


entity = EventSourcedEntity(_SHOPPINGCART, [FILE_DESCRIPTOR], init)
entity = EventSourcedEntity(_SHOPPINGCART, [FILE_DESCRIPTOR], 'carts', init)


def to_domain_line_item(item):
Expand Down Expand Up @@ -207,29 +198,30 @@ def remove_item(state: ShoppingCartState, item: RemoveLineItem, ctx: EventSource
### 4. Register Entity

```
from cloudstate.cloudstate import CloudState
from akkaserverless.akkaserverless_service import AkkaServerlessService
from shoppingcart.shopping_cart_entity import entity as shopping_cart_entity
import logging

if __name__ == '__main__':
logging.basicConfig()
CloudState().register_event_sourced_entity(shopping_cart_entity).start()
service = AkkaServerlessService()
service.add_component(shopping_cart_entity)
service.start()

```

### 5. Deployment

Cloudstate runs on Docker and Kubernetes you need to package your application so that it works as a Docker container
and can deploy it together with Cloudstate Operator on Kubernetes, the details and examples of all of which can be found [here](https://code.visualstudio.com/docs/containers/quickstart-python), [here](https://github.com/cloudstateio/python-support/blob/master/shoppingcart/Dockerfile) and [here](https://cloudstate.io/docs/core/current/user/deployment/index.html).
See [here](https://developer.lightbend.com/docs/akka-serverless/deploying/index.html) for deployment information.

## Contributing

For guidance on setting up a development environment and how to make a contribution to Cloudstate,
see the contributing [project page](https://github.com/cloudstateio/python-support) or consult an official documentation [here](https://cloudstate.io/docs/).
TODO

## Links

* [Website](https://cloudstate.io/)
* [Documentation](https://cloudstate.io/docs/)
* [Releases](https://pypi.org/project/cloudstate/)
* [Code](https://github.com/cloudstateio/python-support)
* [Issue tracker](https://github.com/cloudstateio/python-support/issues)
* [Website](https://https://www.lightbend.com/akka-serverless/)
* [Documentation](https://developer.lightbend.com/docs/akka-serverless/)
* [Releases](https://pypi.org/project/akkaserverless/)
* [Code](https://github.com/jpollock/akkaserverless-python-sdk)
* [Issue tracker](https://github.com/jpollock/akkaserverless-python-sdk/issues)
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ COPY ./requirements.txt /python-support/requirements.txt
RUN pip install -r /python-support/requirements.txt
COPY ./scripts /python-support/scripts
COPY ./protobuf /python-support/protobuf
COPY ./cloudstate /python-support/cloudstate
COPY ./akkaserverless /python-support/akkaserverless
COPY ./setup.py /python-support/setup.py
COPY ./Description.md /python-support/Description.md

RUN /python-support/scripts/fetch-cloudstate-pb.sh master
RUN /python-support/scripts/fetch-akkaserverless-pb.sh master
RUN pip install . -vvv

WORKDIR /
ENTRYPOINT ["python", "-m", "cloudstate.test.tck_services"]
ENTRYPOINT ["python", "-m", "akkaserverless.test.tck_services"]

EXPOSE 8080
EXPOSE 8090
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# Python User Language Support
Python User Language Support for [Cloudstate](https://github.com/cloudstateio/cloudstate).
# Akka Serverless Python SDK

Source code for the Akka Serverless Python package.

For more information see the documentation for [implementing Akka Serverless services in JavaScript](https://developer.lightbend.com/docs/akka-serverless/javascript/).


This package is a fork of the original [Python SDK](https://github.com/cloudstateio/python-support) for [Cloudstate](https://cloudstate.io/). This Akka Serverless package is heavily indebted to the [C]loudstate contributors](https://github.com/cloudstateio/python-support/graphs/contributors), especially [Adriano Santos](https://github.com/sleipnir) and [Marcel Lanz](https://github.com/marcellanz).
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
This package is a fork of the original [Python SDK](https://github.com/cloudstateio/python-support) for [Cloudstate](https://cloudstate.io/). This Akka Serverless package is heavily indebted to the [C]loudstate contributors](https://github.com/cloudstateio/python-support/graphs/contributors), especially [Adriano Santos](https://github.com/sleipnir) and [Marcel Lanz](https://github.com/marcellanz).
This package is a fork of the original [Python SDK](https://github.com/cloudstateio/python-support) for [Cloudstate](https://cloudstate.io/). This Akka Serverless package is heavily indebted to the [Cloudstate contributors](https://github.com/cloudstateio/python-support/graphs/contributors), especially [Adriano Santos](https://github.com/sleipnir) and [Marcel Lanz](https://github.com/marcellanz).

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
This package is a fork of the original [Python SDK](https://github.com/cloudstateio/python-support) for [Cloudstate](https://cloudstate.io/). This Akka Serverless package is heavily indebted to the [C]loudstate contributors](https://github.com/cloudstateio/python-support/graphs/contributors), especially [Adriano Santos](https://github.com/sleipnir) and [Marcel Lanz](https://github.com/marcellanz).
This package is a fork of the original [User Language Support for Python](https://github.com/cloudstateio/python-support) for [Cloudstate](https://cloudstate.io/). This Akka Serverless package is heavily indebted to the [C]loudstate contributors](https://github.com/cloudstateio/python-support/graphs/contributors), especially [Adriano Santos](https://github.com/sleipnir) and [Marcel Lanz](https://github.com/marcellanz).


## Installation via source

```
> git clone https://github.com/cloudstateio/python-support.git
Cloning into 'python-support'...
> git clone https://github.com/jpollock/akkaserverless-python-sdk.git
Cloning into 'akkaserverless-python-sdk'...

> cd python-support
> cd akkaserverless-python-sdk
> python3 -m venv ./venv
> source ./venv/bin/activate
> python --version
Expand All @@ -24,10 +30,13 @@ python setup.py bdist_wheel

### local install
```
python -m pip install dist/cloudstate-<the version>-py3-none-any.whl
python -m pip install dist/akkaserverless-<the version>-py3-none-any.whl
```

### build and run tck, including provisional tests for stateless functions.

NOTE: TODO; this is not setup or developed.

```
./extended_tck.sh
```
Binary file added akkaserverless/.DS_Store
Binary file not shown.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from dataclasses import dataclass, field
from typing import List

from cloudstate.contexts import ClientActionContext
from cloudstate.entity_pb2 import Forward, SideEffect
from akkaserverless.contexts import ClientActionContext
from akkaserverless.akkaserverless.component.component_pb2 import Forward, SideEffect


@dataclass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@

from google.protobuf import descriptor as _descriptor

from cloudstate.action_context import ActionContext
from cloudstate.action_pb2 import _ACTIONPROTOCOL
from akkaserverless.action_context import ActionContext
from akkaserverless.akkaserverless.component.action.action_pb2 import _ACTIONS



@dataclass
Expand All @@ -27,8 +28,8 @@ class Action:
def persistence_id(self):
return self.name()

def entity_type(self):
return _ACTIONPROTOCOL.full_name
def component_type(self):
return "akkaserverless.component.action.Actions"

def unary_handler(self, name: str):
def register_unary_handler(function):
Expand Down
22 changes: 11 additions & 11 deletions cloudstate/action_servicer.py → akkaserverless/action_servicer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,26 @@
from google.protobuf import symbol_database as _symbol_database
from grpc._server import _RequestIterator

from cloudstate.action_context import ActionContext
from cloudstate.action_pb2 import ActionCommand, ActionResponse
from cloudstate.action_pb2_grpc import ActionProtocolServicer
from cloudstate.action_protocol_entity import Action, ActionHandler
from cloudstate.entity_pb2 import ClientAction
from cloudstate.utils.payload_utils import get_payload
from akkaserverless.action_context import ActionContext
from akkaserverless.akkaserverless.component.action.action_pb2 import ActionCommand, ActionResponse
from akkaserverless.akkaserverless.component.action.action_pb2_grpc import ActionsServicer
from akkaserverless.action_protocol_entity import Action, ActionHandler
from akkaserverless.akkaserverless.component.component_pb2 import ClientAction
from akkaserverless.utils.payload_utils import get_payload

_sym_db = _symbol_database.Default()

TYPE_URL_PREFIX = "type.googleapis.com/"


class CloudStateActionProtocolServicer(ActionProtocolServicer):
class AkkaServerlessActionProtocolServicer(ActionsServicer):
def __init__(self, action_protocol_entities: List[Action]):
self.action_protocol_entities = {
entity.name(): entity for entity in action_protocol_entities
}
assert len(action_protocol_entities) == len(self.action_protocol_entities)

def handleUnary(self, request: ActionCommand, context):
def HandleUnary(self, request: ActionCommand, context):
logging.info(f"handling unary {request} {context}.")
if request.service_name in self.action_protocol_entities:
service = self.action_protocol_entities[request.service_name]
Expand Down Expand Up @@ -57,7 +57,7 @@ def handleUnary(self, request: ActionCommand, context):
action_reply.failure.CopyFrom(client_action.failure)
return action_reply

def handleStreamed(self, request_iterator: _RequestIterator, context):
def HandleStreamed(self, request_iterator: _RequestIterator, context):
peek = request_iterator.next() # evidently, the first message has no payload
# and is probably intended to prime the stream handler.
if peek.service_name in self.action_protocol_entities:
Expand Down Expand Up @@ -91,7 +91,7 @@ def handleStreamed(self, request_iterator: _RequestIterator, context):
ctx.fail(str(ex))
logging.exception("Failed to execute command:" + str(ex))

def handleStreamedIn(self, request_iterator, context):
def HandleStreamedIn(self, request_iterator, context):
peek = request_iterator.next() # evidently, the first message has no payload
# and is probably intended to prime the stream handler.
logging.debug(f"peeked: {peek}")
Expand Down Expand Up @@ -125,7 +125,7 @@ def handleStreamedIn(self, request_iterator, context):
ctx.fail(str(ex))
logging.exception("Failed to execute command:" + str(ex))

def handleStreamedOut(self, request, context):
def HandleStreamedOut(self, request, context):
if request.service_name in self.action_protocol_entities:
handler = ActionHandler(self.action_protocol_entities[request.service_name])
else:
Expand Down
Loading