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

Steps and Boilerplate #2

Merged
merged 20 commits into from
Jul 7, 2020
Merged
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
57 changes: 56 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,56 @@
course/node_modules
# logs
logs
*.log
npm-debug.log*

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules
jspm_packages

# Optional npm cache directory
.npm

# webpack
.happypack/
webpack_cache/

# Optional REPL history
.node_repl_history

# Generate directory
render_build
accounts

.vscode

lib

entrypoints.json
jsconfig.json

.DS_Store

**/yarn-error.log
4 changes: 0 additions & 4 deletions .vtexignore

This file was deleted.

89 changes: 65 additions & 24 deletions course/config.json
Original file line number Diff line number Diff line change
@@ -1,47 +1,88 @@
{
"title": "Template Course",
"tagline": "Like a subtitle for your course",
"description": "Description of your course",
"languages": ["en", "pt"],
"title": "Service Course",
"tagline": "Building backend applications with VTEX IO",
"description": "In this course, learn about the main possibilities of backend applications in VTEX IO. Export routes, handle events and connect with external and internal apps, to make your VTEX IO app even better and take the best out of VTEX infrastructure.",
"languages": ["en"],
"steps": [
{
"folder": "01-hello-world",
"title": { "en": "First assignment", "pt": "Primeira tarefa" },
"folder": "00-services",
"title": {
"en": "Services in VTEX IO"
},
"description": {
"en": "Description for the Hello World step (used solely for Github's progress page)",
"pt": "Descrição para o step de Hello World"
"en": "On this step, we have an overview of services in VTEX IO and brief explanation of backend possibilities"
},
"challenge": "none"
},
{
"folder": "02-writing-jsonc",
"folder": "01-boilerplate",
"title": {
"en": "On this step, we have tests that check if some JSONC files were correctly made",
"pt": "Neste passo teremos testes para verificar se alguns arquivos JSONC foram corretamente criados"
"en": "Overview: Understanding the Boilerplate"
},
"description": { "en": "Second description", "pt": "Segunda descrição" },
"challenge": "tests"
"description": {
"en": "Here we have a walkthrough the boilerplate, explaining each file's purpose"
},
"challenge": "none"
},
{
"folder": "03-writing-css",
"folder": "02-events",
"title": {
"en": "Here, we will get some CSS files and parse them, checking if the correct classes were declared",
"pt": "Aqui, iremos parsear arquivos CSS submetidos e verificar se as classes foram corretamente criadas"
"en": "Events: Handling and receiving events"
},
"description": { "en": "Third description", "pt": "Terceira descrição" },
"challenge": "tests"
"description": {
"en": "On this step we approach using events in VTEX IO and learn how to configure an app to listen to events"
},
"challenge": "none"
},
{
"folder": "04-wrapping-up",
"folder": "03-clients-analytics",
"title": {
"en": "Here you can set another title for this step",
"pt": "Aqui você pode colocar outro título para seu step"
"en": "Getting to know more about clients"
},
"description": {
"en": "Every description is required for each step",
"pt": "O campo descrição é obrigatório para todo step"
"en": "Here we have an introduction of clients in VTEX IO and implementation of a external app client"
},
"challenge": "tests"
"challenge": "none"
},
{
"folder": "04-events-triggers",
"title": {
"en": "Events: Using Events as Triggers"
},
"description": {
"en": "Learn how to use an event as triggers to actions"
},
"challenge": "none"
},
{
"folder": "05-clients-masterdata",
"title": {
"en": "Clients: Using Master Data"
},
"description": {
"en": "On this step we approach the Master Data client and its usage"
},
"challenge": "none"
},
{
"folder": "06-graphql-implementation",
"title": {
"en": "GraphQL: Retrieving data from Masterdata"
},
"description": {
"en": "Here we see how to use GraphQL to retrieve data from Mater Data"
},
"challenge": "none"
},
{
"folder": "07-graphiql",
"title": {
"en": "GraphQL: Using GraphiQL"
},
"description": {
"en": "Here we learn how to use GraphiQL to test queries"
},
"challenge": "none"
}
]
}
17 changes: 17 additions & 0 deletions course/steps/00-services/en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Services in VTEX IO

## Introduction

The VTEX IO platform allows developers to create unique commerce experiences using Web technologies. It’s possible to create frontend blocks for Store Framework, backend services exposing REST or GraphQL APIs and combine a series of VTEX modules into a complete solution, packaging it into an app.

As VTEX IO powers big e-commerce operations, they require **running code on a server**. **Services** are how we run **Node.js or .NET** code on VTEX IO infrastructure, backed by API abstractions to improve developer experience.

## Services

A **Service** must be exported from a VTEX IO app, just like themes or store blocks, using builders `node` or `dotnet`. With these, you are able to develop a REST API without having to set up a server.

Services in VTEX IO support one-command rollbacks and continuous integration. They can export internal and external routes and run on top of Kubernetes. You can count on VTEX IO to manage the scalability of your services.

On the `/node` folder of a service lives `service.json`, where it´s possible to **declare routes that the service must respond to** and other configurations like _timeout_ and _memory_.

During this course, you will implement some services in VTEX IO and learn a bit more about the possibilities that they offer to your development.
68 changes: 68 additions & 0 deletions course/steps/01-boilerplate/en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Overview: Understanding the Boilerplate

## Introduction

Making a brief overview of the _Boilerplate_, there are two directories (`/node` and `/graphql`) and the `manifest.json` file, which is an important file to your VTEX IO app because it will be the first communication point with the VTEX IO.

## Manifest Overview

In the `manifest.json` file, you will find the app's name, vendor, version, and other information to pay attention to: builders, policies and dependencies. In this initial state, we have the following configurations:

- builders: what builders your app will need. In this case, we have, so far, only the `docs builder` and the `node builder`, with their respective versions;
- policies: if the app being built needs to access some external services or get some specific data from other places, it needs to declare so, even for external APIs. At this point, we have no specific policies yet;
- dependencies: other VTEX IO apps your app depends on. As addressed below, for this course, we need to also link the `events-example` app, as it is listed as a dependency for this course app.

## `/node` Directory Overview

All directories used over the course are already in this initial project. Most of the directories are empty and will be filled throughout the course.

- `/node/clients`: both files are almost blank and are now just placeholders for the next steps.

- `/node/handlers`: contains a handler that will be used in the next steps.

- `/node/utils`: you will find a file containing global constants declarations (`/node/constants.ts`).

- `/node/index.ts`: contains the initial declarations for the app functionality like the cache declaration and the service declarations, which will be incremented during the course. Here is also possible to export resolver functions implementations.

- `/node/service.json`: It describes your REST API and some characteristics that will directly impact your app's infrastructure attributes.
Your service.json file will be found inside your app's `/node` folder, and will look similar to this:

```
{
"memory": 256,
"timeout": 2,
"minReplicas": 2,
"maxReplicas": 4,
"routes": {
"status": {
"path": "/_v/status/:code",
"public": true
}
}
```

| Field | Type | Description |
| ----------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------- |
| memory | MegaBytes. | How much memory your app will have allocated. This value will be overwritten if IO detects that your app is abusing memory usage |
| timeout | Seconds | VTEX.IO infra will abort the connection if the request time is longer than timeout |
| minReplicas | Integer | When your app is running, how many minimum replicas will be available |
| maxReplicas | Integer | The largest amount of replicas that will be available |
| routes | - | Describes your app's REST routes, inside you will descibe the name, (ex: ssr), the path, and if its public or private |

## `/graphql` Directory Overview

juliarocha marked this conversation as resolved.
Show resolved Hide resolved
On this directory, you will find only the empty directories and the `/graphql/schema.graphql` blank file. This will all be filled throughout the course, as well.

## Dependencies

For this course, this app has a dependency on the `events-example` app. The `events-example` app, when linked to your account and workspace, is responsable for providing events examples. Over the course, as we approach the events topic, there will be a more complete overview of the `events-example` app.

## Activity

1. For now, clone (`git clone`) the `events-example` app from [this repository](https://github.com/vtex-apps/events-example) and run `vtex link` in it's directory.

> Without the `events-example` app, this course app will not be successfully linked, as the `events-example` app is listed as a dependency.

After running `vtex link` on the `events-example` app, the terminal should show a healthcheck route that will be used later. It looks like this:

![image](https://user-images.githubusercontent.com/43679629/83797811-91777480-a679-11ea-9bc9-9d32ace321d7.png)
107 changes: 107 additions & 0 deletions course/steps/02-events/en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Events: Handling and receiving events

## Introduction

Some interactions on VTEX IO can generate events and they can be used as triggers for actions, like the activity on this step. For now, we will use the events fired by the `events-example` app.

## Events on VTEX IO

On VTEX IO apps, events can be fired and used to trigger actions. For example, an app that listens for order placements and triggers a confirmation e-mail. It is important to highlight that events are _workspace and account bound_, which means that events are only visible for the account and workspace where they were fired. Events fired on your personal workspace will only be listened to by apps linked on this same workspace.

## Activity

1. First, we are starting the event firing on the `events-example` app. This app will fire an event every X seconds. After running `vtex link` on the `events-example` directory, click on the healthcheck route available and a "ok" message should appear on the browser:

![image](https://user-images.githubusercontent.com/43679629/83802091-8c69f380-a680-11ea-82af-a438fb73f40b.png)

> This healthcheck route access creates a cache context needed for the VTEX IO to fire events. Without it, the `events-example` app won't be able to fire the events our app is going to listen to.

2. We need to add the event handler on the `Service` declaration to refer to what the app is supposed to do when listening to the event. To do so, on the `/node/index.ts` file, complement `Service` declaration:

```diff
//node/index/ts
export default new Service<Clients, State, ParamsContext>({
clients: {
implementation: Clients,
options: {
default: {
retries: 2,
timeout: 10000,
},
+ events: {
+ exponentialTimeoutCoefficient: 2,
+ exponentialBackoffCoefficient: 2,
+ initialBackoffDelay: 50,
+ retries: 1,
+ timeout: TREE_SECONDS_MS,
+ concurrency: CONCURRENCY,
+ },
+ },
+ },
})
```

Going by each configuration, we have the following:

| Field | Type | Description |
| ------------------------------- | ------- | ------------------------------------------------------------------------------- |
| `exponentialTimeoutCoefficient` | seconds | the exponential factor by which the `timeout` will increase in each retry |
| `exponentialBackoffCoefficient` | seconds | the exponential factor by which the `backoff delay` will increase in each retry |
| `initialBackoffDelay` | seconds | the time the app will wait until the next retry |
| `retries` | - | the maximum times the app will retry |
| `timeout` | seconds | the timeout until consider a failure attempt |
| `concurrency` | - | the amount of simultaneous processes the event is able to perform |

> By adding this code to the `Service`, we are adding to the `Client` of this `Service`, the capability to handle events. At this point, we are not yet using the `Client` itself when handling the event.

3. For now, we are only going to create a log when receiving an event. To create this event handler, in the `/node/event` directory, go to the `liveUsersUpdate.ts` file and do the following:

```ts
//node/event/liveUsersUpdate.ts
export async function updateLiveUsers() {
console.log('EVENT HANDLER: received event')
}
```

4. Now, we need to declare in the `Service` the reference to this function. On the `/node/index.ts` file, add this code:

```diff
...
+ import { updateLiveUsers } from './event/liveUsersUpdate'
...

export default new Service<Clients, State, ParamsContext>({
...
+ events: {
+ liveUsersUpdate: updateLiveUsers,
+ },
})

```

5. We also need to modify the `service.json` file. In order to listen to events sent, we need to declare this to give the app's service this capability. You may do so, by modifying `service.json` file:

```diff
//node/service.json
{
"memory": 128,
"ttl": 10,
"timeout": 10,
"minReplicas": 2,
"maxReplicas": 10,
"workers": 4,
+ "events": {
+ "liveUsersUpdate": {
+ "sender": "vtex.events-example",
+ "keys": ["send-event"]
+ }
},
...
}
```

> Note that we declare this by using the events resolver and the reference of the app that fires the event (declared as `sender`) and the event reference key (declared as `keys`).

6. At last, run `vtex link` and wait for the event to be fired by the `events-example` app. When listened, the log should appear on the console, like this:

![image](https://user-images.githubusercontent.com/43679629/83823425-5f323b00-a6aa-11ea-816a-68525e5800d7.png)
Loading