Last active
November 23, 2018 07:55
-
-
Save ilgooz/08ad2b070f7f7476312cd5b96a0922ee to your computer and use it in GitHub Desktop.
Blog Workflow
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: blog-tutorial | |
description: | | |
A blog workflow | |
Go to blog page at {$configs.domain} to publish some articles! | |
services: | |
# httpServer service serves any content over HTTP. | |
httpServer: https://github.com/ilgooz/service-http-server | |
# website service serves a VueJS app that has features for | |
# articles' creation and listing. | |
# VueJS app makes API calls to RESTful/GraphQL API to manage articles. | |
website: ... | |
# articles service manages articles and stores them in MongoDB. | |
articles: https://github.com/ilgooz/service-articles | |
# mailer service sends emails to receivers with provided content. | |
mailer: https://github.com/mesg-foundation/service-email-sendgrid | |
# location service provides location from ip address. | |
location: https://github.com/ilgooz/service-location | |
# stats service stores stats in a time series database, InfluxDB. | |
# You can watch the stats with Grafana web UI at http://localhost:3000. | |
stats: https://github.com/mesg-foundation/service-influxdb | |
configs: | |
# Domain name for accessing to website and APIs. | |
domain: http://localhost:2300 | |
# SendGrid API key that will be used by mailer service while sending emails. | |
sendgridAPIKey: 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 | |
# noreply mail address of MESG. | |
noRepy: [email protected] | |
# When a new article is created, an email will be sent to each user on this list. | |
defaultUsers: | |
- name: Hey MESG | |
email: [email protected] | |
# start point of the workflow. | |
when: | |
httpserver: | |
event: | |
request: | |
execute: | |
# getPage gets requested page from website application. | |
getPage: | |
website: serve | |
filter: | |
path: | |
match: ^(?!(\/api)).* | |
# we can also introduce ! syntax for ignoring setting empty values. | |
# in that case if a field has ! at the beginning and it's value ends up | |
# being empty, in that case it'll not be set at all. | |
# e.g.: !path | |
map: | |
path: {$event.data.path} | |
host: {$event.data.host} | |
method: {$event.data.method} | |
# servePage serves given page via httpserver. | |
servePage: | |
httpserver: completeSession | |
dependsOn: | |
getPage: success | |
map: | |
sessionID: {$event.data.sessionID} | |
content: {$getPage.data.content} | |
mimeType: {$getPage.data.mimeType} | |
# locateUser finds user's location from ip address. | |
locateUser: | |
location: locate | |
map: | |
ip: {$event.data.userIP} | |
# creates an article if request is made for it. | |
createArticle: | |
articles: save | |
dependsOn: | |
locateUser: location | |
filter: | |
path: | |
match: \/api\/.* | |
method: post | |
map: | |
article: | |
title: {$event.data.article.title} | |
content: {$event.data.article.content} | |
location: | |
country: {$locateUser.data.country} | |
city: {$locateUser.data.city} | |
# serveArticleCreation serves article via httpserver. | |
serveArticleCreation: | |
httpServer: completeSession | |
dependsOn: | |
createArticle: success | |
map: | |
sessionID: {$event.data.sessionID} | |
content: | |
article: {$createArticle.data.article} | |
mimeType: application/json | |
# informUsers execution sends emails to users to notify them about the new article. | |
informUsers: | |
mailer: send | |
dependsOn: | |
createArticle: success | |
map: | |
subject: A New Article Published — {$createArticle.data.title} | |
text: | | |
You can access to article from the link: | |
<a href="{$configs.domain}/{$saveArticle.data.id}">{$createArticle.data.title}</a> | |
from: {$config.noReply} | |
to: {@map($config.users, (user) => {return user.email})} | |
apiKey: {$configs.sendgridAPIKey} | |
logInformUsers: | |
bluelogger: log | |
dependsOn: | |
informUsers: success | |
createArticle: success | |
map: | |
message: users notified for the new '{$createArticle.data.title}' article | |
data: | |
receivers: {$config.users} | |
# recordVisit records every visit to httpServer via stats service. | |
# It uses location info and the name of the endpoint that being requested | |
# as meta data. | |
# You can navigate to Grafana to see this data points in a chart with | |
# the visualised meta data. | |
recordVisit: | |
stats: write | |
dependsOn: | |
locateUser: location | |
!saveArticleCreation: success # ! indicates optional. | |
!website: success | |
map: | |
measurement: {@if( | |
@match(\/api\/.*, $event.data.path), | |
"api_call", | |
"website_visit")} | |
tags: | |
path: {$event.data.path} | |
city: {$locateUser.data.city} | |
country: {$locateUser.data.country} | |
fields: | |
elapsedTime: | |
# oneOf syntax can be useful for getting value from one | |
# of the executions that can executed `optionally` depending | |
# on the flow. | |
# | |
# for this execution we can also wait for a separate event that | |
# httpServer emit after each request completed to reduce complexity | |
# here but oneOf and ! syntax together can be useful for other cases. | |
oneOf: | |
- {$website.data.elapsedTime} | |
- {$saveArticleCreation.data.elapsedTime} | |
value: 1 | |
# logRequest logs http request with additional info. | |
logRequest: | |
bluelogger: log | |
dependsOn: | |
locateUser: location | |
map: | |
message: new http request | |
data: | |
browserInfo: {$event.data.browserInfo} | |
path: {$event.data.path} | |
ip: {$event.data.ip} | |
country: {$locateUser.data.country} | |
city: {$locateUser.data.city} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment