Skip to content

Instantly share code, notes, and snippets.

@ilgooz
Last active November 23, 2018 07:55
Show Gist options
  • Save ilgooz/08ad2b070f7f7476312cd5b96a0922ee to your computer and use it in GitHub Desktop.
Save ilgooz/08ad2b070f7f7476312cd5b96a0922ee to your computer and use it in GitHub Desktop.
Blog Workflow
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: noreply@mesg.com
# When a new article is created, an email will be sent to each user on this list.
defaultUsers:
- name: Hey MESG
email: hey@mesg.com
# 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