santosluiz000 / service-course Goto Github PK
View Code? Open in Web Editor NEWHome Page: https://lab.github.com/vtex-trainings/vtex-io-service-course
Home Page: https://lab.github.com/vtex-trainings/vtex-io-service-course
With the Analytics client implemented, we want to use the Events as trigger to the requests. This means that, for every event listened, we want to perform a request to the Analytics app. So, for every X seconds, we will have a new data on Live Products.
In VTEX IO, events are often used as triggers to other actions, such as sending e-mails to the final client. To implement this, we need to configure our app's client and event handler.
As the Analytics client is implemented, we just need to use it in the event handler. First, in the node/event/liveUsersUpdate.ts
file, import the client we implemented in the previous step:
import { Clients } from '../clients/index'
Now, we need to use the EventContext
that we already configured before. Import it by updating the method. You can do so like this:
//node/event/liveUsersUpdate.ts
import { Clients } from './../clients/index'
+import { EventContext } from '@vtex/api'
+export async function updateLiveUsers(ctx: EventContext<Clients>) {
...
}
Note: you can also globally declare your event context in the
index.ts
file. If you do so, you don't need to import in every file you want to use it.
Now, to use the Analytics client, do the following:
//node/event/liveUsersUpdate.ts
export async function updateLiveUsers(ctx: EventContext<Clients>) {
+ const liveUsersProducts = await ctx.clients.analytics.getLiveUsers()
+ console.log('LIVE USERS: ', liveUsersProducts)
+ return true
}
Finally, run vtex link
and for every event fired, you should see the live users retrieved from the Analytics.
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.
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:
docs builder
and the node builder
, with their respective versions;events-example
app, as it is listed as a dependency for this course app./node
Directory OverviewAll 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 it is also possible to export resolver functions implementations (for GraphQL).
/node/service.json
: 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 it's public or private |
/graphql
Directory OverviewOn 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.
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 responsible 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.
git clone
) the events-example
app from this repository and run vtex link
in it's directory.Without the
events-example
app, this course app will not be successfully linked, as theevents-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:
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.
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.
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:
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.
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:
//node/index/ts
+ const THREE_SECONDS_MS = 3 * 1000
+ const CONCURRENCY = 10
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 theClient
of thisService
, the capability to handle events. At this point, we are not yet using theClient
itself when handling the event.
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:
//node/event/liveUsersUpdate.ts
export async function updateLiveUsers() {
console.log('EVENT HANDLER: received event')
}
Now, we need to declare in the Service
the reference to this function. On the /node/index.ts
file, add this code:
...
+ import { updateLiveUsers } from './event/liveUsersUpdate'
...
export default new Service<Clients, State, ParamsContext>({
...
+ events: {
+ liveUsersUpdate: updateLiveUsers,
+ },
})
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:
//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 askeys
).
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:
In this step, we briefly explain some clients concepts and present the clients that will be necessary for this course: analytics client and master data client. The first one will be implemented on this step, and you'll also learn how to use a client that has been already implemented in our API.
Clients, on VTEX IO, are abstractions to other services. We tackle complexities when setting up an HTTP client, for example, so you can focus on the real value of your software. Whenever you need to setup a connection with an external API or another VTEX service, you should create a client! Some standard clients are already baked into VTEX IO, check them here.
If you already got to know more about IO services, you probably know that your implementation exports functions that receive a context object. These functions can be a resolver function to a GraphQL field, a middleware to an HTTP server or an event handler, and, in all of them, you receive a ctx (or however you wanna call it) object of type Context
, and it is inside of ctx.clients
where you’ll find each client.
It's possible to read more about clients concepts on this document.
In this course, it will be necessary to create a client that will be used to get information regarding product's number of views. The client that will be created will make a REST request in which it'll retrieve information about product views. This client needs to have a function that will be used on a handler for a specific route and this is how it can be tested.
In this step, we will implement the Analytics client. So,
First, in the /node/clients/
directory, you will find a file called analytics.ts
, which already has a sketch, just like the code block below. This is where you'll implement your client.
//node/clients/analytics.ts
import { AppClient } from '@vtex/api'
export default class Analytics extends AppClient {}
You can see in this code block that
Analytics
is a client that extends fromAppClient
because this class offers pre-configurations that assure that your client has secure communication with other parts of your app.
The client needs to have a constructor and just a single method, called getLiveUsers
. This method returns a promise of an array that its elements are of the type LiveUsersProduct
. Using the code below, add the necessary code lines to the client:
//node/clients/analytics.ts
+import { AppClient, InstanceOptions, IOContext } from '@vtex/api'
export default class Analytics extends AppClient {
+ constructor(context: IOContext, options?: InstanceOptions) {
+ super('[email protected]', context, options)
+ }
+ public getLiveUsers(): Promise<LiveUsersProduct[]> {}
}
+interface LiveUsersProduct {
+ slug: string
+ liveUsers: number
+}
The interface that is defined is going to be used as a typing on the method that we'll implement.
Now it's necessary to implement the getLiveUsers
method. It returns an HTTP GET request to a well-defined endpoint that is responsible for getting the data that is needed in this application. So add the following line to the method getLiveUsers
:
return this.http.get('_v/live-products')
The method that you've just created will get the necessary data for this application: an array of objects that have two fields:
slug
, a string that represents the product ID andliveUsers
, a number that is the quantity of users visualizing this product - which are the fields in the interface.
The _v/live-products
API endpoint we call above needs the app mocked-analytics
to run, or your getLiveUsers
method will not see anything there. In case of not running this application on appliancetheme
account, you will have to install the mocked-analytics
app on your workspace. To do that, you can run vtex install vtex.mocked-analytics
.
With your analytics client already implemented, it's necessary to declare it as one of the clients in the Clients
class, so it will be accessible using the Context
that we've talked about at the beginning of this step.
So, in the node/clients/
directory, go to the file called index.ts
and add a get method to the class that refers to the analytics client. It's also necessary to import the client that you created.
// node/clients/index.ts
+ import Analytics from '../clients/analytics'
export class Clients extends IOClients {
+ public get analytics() {
+ return this.getOrSet('analytics', Analytics)
}
}
So as to see it working, it's possible to use getLiveUsers
method inside the handler for the analytics client. Using a route that it's already defined in the project, it is possible to send a request to it and the handler responsible for this route will call the method that we created.
Inside the node directory, there is a folder called handlers
. There is already a file named analytics.ts
, in which it's necessary to do two things for your test to work: get the analytics client from ctx
and replace the content of ctx.body
with the method mentioned before, as you can see in the code block below:
export async function analytics(ctx: Context, next: () => Promise<any>) {
+ const {
+ clients: { analytics },
+ } = ctx
+ ctx.status = 200
- ctx.body = 'OK'
+ ctx.body = await analytics.getLiveUsers()
+ ctx.set('cache-control', 'no-cache')
await next()
}
Now let's test it! It's possible to use Postman to send a GET
request to the following route:
{your workspace}--{your account}.myvtex.com/_v/app/analytics/realTime
and it's expected that it replies with the data and status 200
.
Attention! Generally, the account where you're running the app is
appliancetheme
.
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.
It's important for you to have our test bot installed in this course repository. With it installed, we can see your progress, even though it does not contain any tests or evaluations on each step (as in other courses we offer). To install it, follow the steps below:
Open our test bot installation page and click on Configure;
Select the Only selected repositories option, then click on Select repositories and type in service-course
;
Click on santosluiz000/service-course
and then on Install.
Note: The image above shows the process for
store-block
, but the steps forservice-course
are the same.
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, GraphQL APIs and routes.
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.
Inside 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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.