Skip to content

Commit

Permalink
upgrading
Browse files Browse the repository at this point in the history
  • Loading branch information
balazskreith committed Aug 10, 2022
1 parent 6afd504 commit eb5ba29
Show file tree
Hide file tree
Showing 103 changed files with 4,216 additions and 1,672 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.

name: Publish package to GitHub Packages
on:
release:
types: [created]

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
- name: Publish package
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
gradle/
build/
.idea/
.gradle/
.gradle/
keys/
150 changes: 142 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,174 @@
Hamok
---

Light and convenient library to create a simple storage grid.
Light and convenient library to create a distributed in-memory object storage grid for java.

## Quick Start
```java
// construct the endpoint of the storage grid
var server_1 = StorageGrid.builder().build();
var server_2 = StorageGrid.builder().build();

// connect the constructed endpoint to each other
server_1.transport().sender().subscribe(server_2.transport().receiver())
server_2.transport().sender().subscribe(server_1.transport().receiver())

// create a storage automatically replicates itself through the grid
var replicatedStorage_1 = server_1.<Integer, String>replicatedStorage().setStorageId("my-distributed-storage").build();
var replicatedStorage_2 = server_2.<Integer, String>replicatedStorage().setStorageId("my-distributed-storage").build();

replicatedStorage_1.set(1, "one");
System.out.println(replicatedStorage_2.get(1));
```

Where `server_1` and `server_2` are created in two different server applications, and the transport is handled by the servers with each other.
Where `server_1` and `server_2` are created in two different server instances, and the transport is handled by the servers to each other.

## Table of Contents
* []()
* [Concept](#concept)
* [Storages](#storages)
* [Storage Grids](#storage-grids)
*

## Concept

Horizontal scalability becomes a standard requirement of designing services today.
A running service stores objects in the local-memory of the server instance
they are running on, but they often require sharing objects with each
other for various purposes.

For example when two or more clients sending measurements to two server instances,
at some point one instance might need to query the number of total clients,
or the last measurement value of a specific client received by another instance.
This can only be possible if the objects stored by the instances are shared.
The basic need to share objects between services may not require to add a
database as an additional dependency. Here comes Hamok into the picture.

Hamok is designed to be a lightweight, distributed object storage with minimal
effort to create and maximal flexibility to utilize. It includes the necessary logic to
embed the library and use shared object storages, meanwhile it relies on
the application developer to manage the cluster of the service.


## Storages

### Built-in storages
Before we go to the distributed storage grids, let's clarify what a storage means in hamok.
Storage in hamok is a key, value object map providing the following basic operations:
insert, set, get, delete, clear. Additionally, every storage provide events
to notify subscribers when a storage is altered or closed.

The concrete implementation of a hamok storage varies based on requirements.
A concrete storage can be a simple memory storage, a concurrent time limited memory storage,
or a client library of a database representing a table as a storage.

Using a Storage interface in your application, but changing the actual storage
instance based on environment (simple memory storage in test, database representation in prod, etc.)
gives the flexibility for the developers to decompose the service they are developing from the
underlying representation.

One more note, before we go to the Storage Grid sections. Each storage provides a method
for batched operations (insertAll, setAll, getAll, deleteAll), which are preferred if performance
comes into the picture.

## Storage grids

Storage grids are the entry points for distributed storages.

Hamok does not provide locks as part of the distributed storages. As strange as it sounds,
it attempts to address the problem of distributed concurrent modifications
by relying on the developer to choose the right concept for storing objects for different scenarios.
There are three type of distributed storages in hamok: Replicated, Separated, and Federated.
Each storage type is developed for different scenarios, and the scenarios are detailed in
storage descriptions.

Hamok uses Raft as a consensus algorithm. Raft is combined with a so-called
discovery protocol in hamok, and the combined package called raccoons.

### Create Storage Grids

### Raft + Discovery (Raccoon)

Raccoon is a combination of [Raft](https://raft.github.io/) and the hamok discovery protocol.
Each StorageGrid craetes a raccoon internally.
If StorageGrid auto-discovery is enabled and StorageGrid transports are connected,
Raccoons discovering each other by sending hello messages. When a cluster is formed,
raccoons elect a leader based on raft. The elected leader ensures consistency in the cluster
for storages requires it (i.e.: ReplicatedStorage).

### Separated Storage

An object in the storage is mutated by only one server instance.
Every server instance can access to every object by key,
but only one instance modifies one object belongs to a specific key.
The instance modifies the object does not have to store it locally.

For example, a client application collect the temperature for a given
coordinates and send it to service scale horizontally and share
the storage identified as temperatures amongst the instances.
The key of the measurement is a geographical coordinate, and the value
is the measured temperature.

```java
// after you defined your storage grid
var keyCodec = Codec.create(GeoLocation::toString, GeoLocation::fromString);
var valueCodec = Codec.create(d -> d.toString(), Double::parseDouble);
var temperatures = storageGrid.<GeoLocation, Double>separatedStorage()
.setStorageId("temperatures")
.setKeyCodec(() -> keyCodec)
.setValueCodecSupplier(() -> valueCodec)
.build();

// ... client received measurements
temperatures.set(measurement.location, measurement.temperature);
```

NOTE: GeoLocation is a custom class

### Federated Storage

An object in the storage is a combination of multiple subpart stored in
one or more server instances. Each time an object is accessed by a key at any server
instance, the server instance requests the subpart from all other
server instances and provide the result as the combination of the
responses.

Keeping the

A globally available object in the storage for a key is a combination of
multiple locally altered objects by several instances and the result is the
combination of all instance locally stored objects for a given key.

### Replicated Storage

### Custom storages

## Storage Grid

## Reactive Events
### CAP analysis

Consistency and Availability: For federated and separated storages the consistency and
availability rely on the developer creates the storage. In case of
replicated storage, consistency is ensured by raft.

Partition tolerance: In case of message dropped by the network or any request failure,
the StorageGrid retries it. The number of retries is configurable when the
StorageGrid is built.

## Codecs

## Transports

## Collections

## Developer Manual

## Contribution

## License



## Sentence purgatory

In case you have a service collect measurements from client
applications, and the measurements are separated and should be shared amongst all
instances of the service, Separated Storage can be choice. It
makes the collected measurements available amongst all server instances,
meanwhile only one client provides the measurements mutate the storage
for a given key (the key can be for example the client identifier).
56 changes: 56 additions & 0 deletions WEBPAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
Hamok
---
Light and convenient library to create a distributed object storage.


## Quick start

#### Java

```java

```

#### Typescript

```typescript

```

## Basic concept

Horizontal scalability becomes a standard requirement of designing services today.
A running service stores objects in the local-memory of the server instance
they are running on, but they often require sharing objects with each
other for various purposes.

For example when two or more clients sending measurements to two server instances,
at some point one instance might need to query the number of total clients,
or the last measurement value of a specific client received by another instance.
This can only be possible if the objects stored by the instances are shared.
The basic need to share objects between services may not require to add a
database as an additional dependency. Here comes Hamok into the picture.

Hamok is designed to be a lightweight, distributed object storage with minimal
effort to create and maximal flexibility to utilize. It includes the necessary logic to
embed the library and use shared object storages, meanwhile it relies on
the application developer to manage the cluster of the service.

## Storages

## Storage grids

### Raft + Discovery (Raccoon)

### Replicated Storage

### Separated Storage

### Federated Storage

## Language bindings

### Java

### Typescript

40 changes: 31 additions & 9 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
plugins {
id 'java'
id 'maven-publish'
}

group 'com.balazskreith.vstorage'
group 'io.github.balazskreith.hamok'
version '1.0.0-beta'

repositories {
Expand All @@ -16,22 +17,43 @@ java {


dependencies {
// runtimeOnly("ch.qos.logback:logback-classic")

implementation "io.reactivex.rxjava3:rxjava:3.1.5"
// implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.3'

implementation 'org.slf4j:slf4j-api:1.7.30'
// implementation 'org.apache.logging.log4j:log4j-slf4j-impl'

// implementation 'org.slf4j:slf4j-simple:1.7.30'

testImplementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.11'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testImplementation group: 'io.netty', name: 'netty-all', version: '4.1.79.Final'

testImplementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.3'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

publishing {
repositories {
maven {
name = "OSSRH"
url = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
credentials {
username = System.getenv("MAVEN_USERNAME")
password = System.getenv("MAVEN_PASSWORD")
}
}
// maven {
// name = "GitHubPackages"
// url = "https://maven.pkg.github.com/balazskreith/hamok"
// credentials {
// username = System.getenv("GITHUB_ACTOR")
// password = System.getenv("GITHUB_TOKEN")
// }
// }
}
publications {
gpr(MavenPublication) {
from(components.java)
}
}
}

test {
useJUnitPlatform()
}
Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 5 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit eb5ba29

Please sign in to comment.