Skip to content

Commit

Permalink
Merge branch 'release/0.9.0' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
ljupcovangelski committed Feb 16, 2021
2 parents d7c8d91 + 1c63eba commit a59dd07
Show file tree
Hide file tree
Showing 210 changed files with 4,992 additions and 2,476 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ jobs:
- name: Upload airy binary to S3
if: startsWith(github.ref, 'refs/heads/release') || startsWith(github.ref, 'refs/heads/main')
run: |
aws s3 cp bazel-bin/infrastructure/cli/airy_linux_bin s3://airy-core-binaries/`cat ./VERSION`/linux/amd64/airy
aws s3 cp bazel-bin/infrastructure/cli/airy_darwin_bin s3://airy-core-binaries/`cat ./VERSION`/darwin/amd64/airy
aws s3 cp bazel-bin/infrastructure/cli/airy_windows_bin s3://airy-core-binaries/`cat ./VERSION`/windows/amd64/airy.exe
./scripts/upload-cli-binaries.sh
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Expand Down
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
docs/docs/cli/*.md
docs/docs/cli/reference.md
build/
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@



# Airy Core Platform
# Airy Core

[![Join the chat on Airy community](https://img.shields.io/badge/forum-join%20discussions-brightgreen.svg)](https://airy.co/community/?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Documentation Status](https://img.shields.io/badge/docs-stable-brightgreen.svg)](https://docs.airy.co/)
[![CI](https://github.com/airyhq/airy/workflows/CI/badge.svg)](https://github.com/airyhq/airy/actions?query=workflow%3ACI)
[![Commit Frequency](https://img.shields.io/github/commit-activity/m/airyhq/airy)](https://docs.airy.co/)
[![License](https://img.shields.io/github/license/airyhq/airy)](https://docs.airy.co/)
[![Commit Frequency](https://img.shields.io/github/commit-activity/m/airyhq/airy)](https://github.com/airyhq/airy/pulse)
[![License](https://img.shields.io/github/license/airyhq/airy)](https://github.com/airyhq/airy/blob/develop/LICENSE)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/airyhq/airy/projects)


The Airy Core Platform is an open source, fully-featured, production ready
Airy Core is an open source, fully-featured, production ready
messaging platform.
With Airy you can process conversational data from a variety of sources:

Expand Down Expand Up @@ -73,7 +73,7 @@ Learn more about what we open-sourced in the

## Getting started

You can run the Airy Core Platform locally by running the following commands:
You can run Airy Core locally by running the following commands:

```sh
$ git clone https://github.com/airyhq/airy
Expand All @@ -89,7 +89,7 @@ deployment guide](/docs/docs/getting-started/deployment/test-environment.md) for

## Components

The Airy Core Platform contains the following components:
Airy Core contains the following components:

- An ingestion platform that heavily relies on [Apache
Kafka](https://kafka.apache.org) to process incoming webhook data from
Expand All @@ -110,7 +110,7 @@ The Airy Core Platform contains the following components:
## Organization of the Repository

This [monorepo](https://en.wikipedia.org/wiki/Monorepo) contains all the
code and tooling required to run the Airy Core Platform.
code and tooling required to run Airy Core.

Here is a quick overview of how the repository is organized:

Expand Down Expand Up @@ -147,7 +147,7 @@ If you wish to learn more about a specific project, refer to the

## Design Principles

The Airy Core Platform is built using a few guiding principles. An introduction
Airy Core is built using a few guiding principles. An introduction
to these principles is essential to navigate the code base with ease. You can
read more about it [here](/docs/docs/guidelines/design-principles.md)

Expand All @@ -168,7 +168,7 @@ started.

## Code of Conduct

To ensure a safe experience and a welcoming community, the Airy Core Platform
To ensure a safe experience and a welcoming community, Airy Core
project adheres to the [contributor
convenant](https://www.contributor-covenant.org/) [code of
conduct](/code_of_conduct.md).
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.8.1
0.9.0
1 change: 1 addition & 0 deletions backend/api/admin/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ app_deps = [
"//backend:tag",
"//backend:webhook",
"//backend/model/metadata",
"//backend/model/template",
"//lib/java/uuid",
"//lib/java/spring/auth:spring-auth",
"//lib/java/spring/web:spring-web",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import co.airy.avro.communication.ChannelConnectionState;
import co.airy.avro.communication.Metadata;
import co.airy.avro.communication.Tag;
import co.airy.avro.communication.Template;
import co.airy.avro.communication.Webhook;
import co.airy.kafka.schema.application.ApplicationCommunicationChannels;
import co.airy.kafka.schema.application.ApplicationCommunicationMetadata;
import co.airy.kafka.schema.application.ApplicationCommunicationTags;
import co.airy.kafka.schema.application.ApplicationCommunicationTemplates;
import co.airy.kafka.schema.application.ApplicationCommunicationWebhooks;
import co.airy.kafka.streams.KafkaStreamsWrapper;
import co.airy.model.channel.dto.ChannelContainer;
Expand Down Expand Up @@ -46,6 +48,7 @@ public class Stores implements HealthIndicator, ApplicationListener<ApplicationS
private final String connectedChannelsStore = "connected-channels-store";
private final String tagsStore = "tags-store";
private final String webhooksStore = "webhook-store";
private final String templatesStore = "templates-store";

// Using a UUID as the default key for the webhook will make it easier
// to add multiple webhooks if that ever becomes a requirement
Expand All @@ -55,6 +58,7 @@ public class Stores implements HealthIndicator, ApplicationListener<ApplicationS
private final String applicationCommunicationWebhooks = new ApplicationCommunicationWebhooks().name();
private final String applicationCommunicationTags = new ApplicationCommunicationTags().name();
private final String applicationCommunicationMetadata = new ApplicationCommunicationMetadata().name();
private final String applicationCommunicationTemplates = new ApplicationCommunicationTemplates().name();

public Stores(KafkaStreamsWrapper streams, KafkaProducer<String, SpecificRecordBase> producer) {
this.streams = streams;
Expand All @@ -81,6 +85,8 @@ public void onApplicationEvent(ApplicationStartedEvent event) {

builder.<String, Tag>table(applicationCommunicationTags, Materialized.as(tagsStore));

builder.<String, Template>table(applicationCommunicationTemplates, Materialized.as(templatesStore));

streams.start(builder.build(), appId);
}

Expand Down Expand Up @@ -120,15 +126,32 @@ public void deleteTag(Tag tag) {
producer.send(new ProducerRecord<>(applicationCommunicationTags, tag.getId(), null));
}

public void storeTemplate(Template template) throws ExecutionException, InterruptedException {
producer.send(new ProducerRecord<>(applicationCommunicationTemplates, template.getId(), template)).get();
}

public void deleteTemplate(Template template) {
producer.send(new ProducerRecord<>(applicationCommunicationTemplates, template.getId(), null));
}

public ReadOnlyKeyValueStore<String, ChannelContainer> getConnectedChannelsStore() {
return streams.acquireLocalStore(connectedChannelsStore);
}

public ReadOnlyKeyValueStore<String, Template> getTemplatesStore() {
return streams.acquireLocalStore(templatesStore);
}

public ChannelContainer getChannel(String channelId) {
final ReadOnlyKeyValueStore<String, ChannelContainer> store = getConnectedChannelsStore();
return store.get(channelId);
}

public Template getTemplate(String templateId) {
final ReadOnlyKeyValueStore<String, Template> store = getTemplatesStore();
return store.get(templateId);
}

public List<ChannelContainer> getChannels() {
final ReadOnlyKeyValueStore<String, ChannelContainer> store = getConnectedChannelsStore();

Expand All @@ -140,9 +163,17 @@ public List<ChannelContainer> getChannels() {
return channels;
}

public List<Template> getTemplates() {
final KeyValueIterator<String, Template> iterator = getTemplatesStore().all();

List<Template> templates = new ArrayList<>();
iterator.forEachRemaining(kv -> templates.add(kv.value));

return templates;
}

public Webhook getWebhook() {
final ReadOnlyKeyValueStore<String, Webhook> webhookStore = getWebhookStore();

return webhookStore.get(allWebhooksKey);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package co.airy.core.api.admin;

import co.airy.avro.communication.Template;
import co.airy.core.api.admin.payload.CreateTemplateRequestPayload;
import co.airy.core.api.admin.payload.DeleteTemplateRequestPayload;
import co.airy.core.api.admin.payload.GetTemplateRequestPayload;
import co.airy.core.api.admin.payload.ListTemplatesRequestPayload;
import co.airy.core.api.admin.payload.TemplatesResponsePayload;
import co.airy.core.api.admin.payload.UpdateTemplateRequestPayload;
import co.airy.model.template.TemplatePayload;
import co.airy.spring.web.payload.EmptyResponsePayload;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutionException;

import static java.util.stream.Collectors.toList;

@RestController
public class TemplatesController {
private final Stores stores;
private final ObjectMapper objectMapper;

public TemplatesController(Stores stores, ObjectMapper objectMapper) {
this.stores = stores;
this.objectMapper = objectMapper;
}

@PostMapping("/templates.create")
ResponseEntity<?> createTemplate(@RequestBody @Valid CreateTemplateRequestPayload payload) throws JsonProcessingException {
final Template template = Template.newBuilder()
.setId(UUID.randomUUID().toString())
.setName(payload.getName())
.setContent(payload.getContent())
.setVariables(objectMapper.writeValueAsString(payload.getVariables()))
.build();

try {
stores.storeTemplate(template);
} catch (InterruptedException | ExecutionException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}

return ResponseEntity.status(201).body(TemplatePayload.fromTemplate(template));
}

@PostMapping("/templates.info")
ResponseEntity<?> getTemplate(@RequestBody @Valid GetTemplateRequestPayload payload) {
final Template template = stores.getTemplatesStore().get(payload.getId().toString());
if (template == null) {
return ResponseEntity.notFound().build();
}

return ResponseEntity.ok(TemplatePayload.fromTemplate(template));
}

@PostMapping("/templates.delete")
ResponseEntity<?> deleteTemplate(@RequestBody @Valid DeleteTemplateRequestPayload payload) {
final Template template = stores.getTemplatesStore().get(payload.getId().toString());
if (template == null) {
return ResponseEntity.notFound().build();
}
stores.deleteTemplate(template);
return ResponseEntity.ok(new EmptyResponsePayload());
}

@PostMapping("/templates.list")
ResponseEntity<?> listTemplates(@RequestBody @Valid ListTemplatesRequestPayload payload) {
final List<TemplatePayload> response = stores.getTemplates().stream()
.filter(t -> {
if (payload.getName() == null || payload.getName().isEmpty()) {
return true;
}
return t.getName().contains(payload.getName());
})
.map(TemplatePayload::fromTemplate)
.collect(toList());

return ResponseEntity.ok(new TemplatesResponsePayload(response));
}

@PostMapping("/templates.update")
ResponseEntity<?> updateTemplate(@RequestBody @Valid UpdateTemplateRequestPayload payload) throws JsonProcessingException {
final Template template = stores.getTemplate(payload.getName());

if (template == null) {
return ResponseEntity.notFound().build();
}

template.setContent(payload.getName());
template.setContent(objectMapper.writeValueAsString(payload.getContent()));

try {
stores.storeTemplate(template);
} catch (InterruptedException | ExecutionException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}

return ResponseEntity.ok(TemplatePayload.fromTemplate(template));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package co.airy.core.api.admin.payload;

import com.fasterxml.jackson.databind.JsonNode;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CreateTemplateRequestPayload {
@NotNull
private String name;
@NotNull
private String content;
@Valid
@NotNull
private JsonNode variables;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package co.airy.core.api.admin.payload;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotNull;
import java.util.UUID;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeleteTemplateRequestPayload {
@NotNull
private UUID id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package co.airy.core.api.admin.payload;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotNull;
import java.util.UUID;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class GetTemplateRequestPayload {
@NotNull
private UUID id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package co.airy.core.api.admin.payload;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ListTemplatesRequestPayload {
private String name;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package co.airy.core.api.admin.payload;

import co.airy.model.template.TemplatePayload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TemplatesResponsePayload {
private List<TemplatePayload> data;
}
Loading

0 comments on commit a59dd07

Please sign in to comment.