Add Akka-Streams to Assess

This commit is contained in:
Carsten Lenz
2017-09-12 22:50:42 +02:00
committed by Tom Raithel
parent 9bac3a27b2
commit 86188db1a7
5 changed files with 123 additions and 129 deletions

View File

@@ -1,43 +1,50 @@
export const featuredOnly = items => items.filter(item => item.isFeatured);
export const groupByQuadrants = (items) => (
items.reduce((quadrants, item) => ({
...quadrants,
[item.quadrant]: addItemToQuadrant(quadrants[item.quadrant], item),
}), {})
);
export const groupByQuadrants = items =>
items.reduce(
(quadrants, item) => ({
...quadrants,
[item.quadrant]: addItemToQuadrant(quadrants[item.quadrant], item),
}),
{},
);
export const groupByRing = (items) => (
items.reduce((rings, item) => ({
...rings,
[item.ring]: addItemToList(rings[item.ring], item),
}), {})
);
export const groupByRing = items =>
items.reduce(
(rings, item) => ({
...rings,
[item.ring]: addItemToList(rings[item.ring], item),
}),
{},
);
export const groupByFirstLetter = (items) => {
const index = items.reduce((letterIndex, item) => ({
...letterIndex,
[getFirstLetter(item)]: addItemToList(letterIndex[getFirstLetter(item)], item),
}), {});
export const groupByFirstLetter = items => {
const index = items.reduce(
(letterIndex, item) => ({
...letterIndex,
[getFirstLetter(item)]: addItemToList(
letterIndex[getFirstLetter(item)],
item,
),
}),
{},
);
return Object.keys(index).sort().map((letter) => ({
letter,
items: index[letter],
}));
}
return Object.keys(index)
.sort()
.map(letter => ({
letter,
items: index[letter],
}));
};
const addItemToQuadrant = (quadrant = {}, item) => ({
...quadrant,
[item.ring]: addItemToRing(quadrant[item.ring], item),
});
const addItemToList = (list = [], item) => ([
...list,
item,
]);
const addItemToList = (list = [], item) => [...list, item];
const addItemToRing = (ring = [], item) => ([
...ring,
item,
]);
const addItemToRing = (ring = [], item) => [...ring, item];
export const getFirstLetter = (item) => item.title.substr(0,1).toUpperCase();
export const getFirstLetter = item => item.title.substr(0, 1).toUpperCase();

View File

@@ -3,17 +3,14 @@ import path from 'path';
import frontmatter from 'front-matter';
import marked from 'marked';
import hljs from 'highlight.js';
import {
radarPath,
getAllMarkdownFiles,
} from './file';
import { radarPath, getAllMarkdownFiles } from './file';
marked.setOptions({
highlight: (code) => hljs.highlightAuto(code).value,
highlight: code => hljs.highlightAuto(code).value,
});
export const createRadar = async (tree) => {
const fileNames = (await getAllMarkdownFiles(radarPath()));
export const createRadar = async tree => {
const fileNames = await getAllMarkdownFiles(radarPath());
const revisions = await createRevisionsFromFiles(fileNames);
const allReleases = getAllReleases(revisions);
const items = createItems(revisions);
@@ -28,83 +25,80 @@ export const createRadar = async (tree) => {
const checkAttributes = (fileName, attributes) => {
const rings = ['adopt', 'trial', 'assess', 'hold'];
if (attributes.ring && !rings.includes(attributes.ring)) {
throw new Error(`Error: ${fileName} has an illegal value for 'ring' - must be one of ${rings}`);
throw new Error(
`Error: ${fileName} has an illegal value for 'ring' - must be one of ${rings}`,
);
}
const quadrants = ['languages-and-frameworks', 'methods-and-patterns', 'platforms-and-aoe-services', 'tools'];
const quadrants = [
'languages-and-frameworks',
'methods-and-patterns',
'platforms-and-aoe-services',
'tools',
];
if (attributes.quadrant && !quadrants.includes(attributes.quadrant)) {
throw new Error(`Error: ${fileName} has an illegal value for 'quadrant' - must be one of ${quadrants}`);
throw new Error(
`Error: ${fileName} has an illegal value for 'quadrant' - must be one of ${quadrants}`,
);
}
};
const createRevisionsFromFiles = (fileNames) => (
Promise.all(fileNames.map((fileName) => {
return new Promise((resolve, reject) => {
readFile(fileName, 'utf8', (err, data) => {
if(err) {
reject(err);
} else {
const fm = frontmatter(data);
// prepend subfolder to links
fm.body = fm.body.replace(/\]\(\//g, '](/techradar/')
const createRevisionsFromFiles = fileNames =>
Promise.all(
fileNames.map(fileName => {
return new Promise((resolve, reject) => {
readFile(fileName, 'utf8', (err, data) => {
if (err) {
reject(err);
} else {
const fm = frontmatter(data);
// prepend subfolder to links
fm.body = fm.body.replace(/\]\(\//g, '](/techradar/');
// add target attribute to external links
let html = marked(fm.body);
html = html.replace(/a href="http/g, 'a target="_blank" href="http')
// add target attribute to external links
let html = marked(fm.body);
html = html.replace(
/a href="http/g,
'a target="_blank" href="http',
);
checkAttributes(fileName, fm.attributes);
resolve({
...itemInfoFromFilename(fileName),
...fm.attributes,
fileName,
body: html
});
}
checkAttributes(fileName, fm.attributes);
resolve({
...itemInfoFromFilename(fileName),
...fm.attributes,
fileName,
body: html,
});
}
});
});
})
}))
);
}),
);
const itemInfoFromFilename = (fileName) => {
const [
release,
nameWithSuffix,
] = fileName.split(path.sep).slice(-2);
const itemInfoFromFilename = fileName => {
const [release, nameWithSuffix] = fileName.split(path.sep).slice(-2);
return {
name: nameWithSuffix.substr(0, nameWithSuffix.length - 3),
release,
}
};
};
const getAllReleases = (revisions) => (
revisions.reduce((allReleases, { release }) => {
if(!allReleases.includes(release)) {
return [...allReleases, release];
}
return allReleases;
}, []).sort()
);
// const createQuadrants = (revisions) => (
// revisions.reduce((quadrants, revision) => {
// return {
// ...quadrants,
// [revision.quadrant]: addRevisionToQuadrant(quadrants[revision.quadrant], revision),
// };
// }, {})
// );
// const addRevisionToQuadrant = (quadrant = {}, revision) => ({
// ...quadrant,
// [revision.name]: addRevisionToItem(quadrant[revision.name], revision),
// });
const getAllReleases = revisions =>
revisions
.reduce((allReleases, { release }) => {
if (!allReleases.includes(release)) {
return [...allReleases, release];
}
return allReleases;
}, [])
.sort();
const addRevisionToQuadrant = (quadrant = {}, revision) => ({
...quadrant,
[revision.ring]: addRevisionToRing(quadrant[revision.ring], revision),
});
const createItems = (revisions) => {
const createItems = revisions => {
const itemMap = revisions.reduce((items, revision) => {
return {
...items,
@@ -112,21 +106,18 @@ const createItems = (revisions) => {
};
}, {});
return Object
.values(itemMap)
.sort((x, y) => (x.name > y.name ? 1 : -1));
return Object.values(itemMap).sort((x, y) => (x.name > y.name ? 1 : -1));
};
const addRevisionToItem = (item = {
attributes: {
const addRevisionToItem = (
item = {
isNew: false,
isFeatured: true,
revisions: [],
},
revisions: [],
}, revision) => {
const {
fileName,
...rest,
} = revision;
revision,
) => {
const { fileName, ...rest } = revision;
let newItem = {
...item,
...rest,
@@ -139,28 +130,29 @@ const addRevisionToItem = (item = {
if (revisionCreatesNewHistoryEntry(revision)) {
newItem = {
...newItem,
revisions: [
rest,
...newItem.revisions,
],
}
revisions: [rest, ...newItem.revisions],
};
}
return newItem;
};
const revisionCreatesNewHistoryEntry = (revision) => {
return revision.body.trim() !== '' ||
typeof revision.ring !== 'undefined';
const revisionCreatesNewHistoryEntry = revision => {
return revision.body.trim() !== '' || typeof revision.ring !== 'undefined';
};
const flagWithIsNew = (items, allReleases) => (
items.map((item) => ({
...item,
isNew: isNewItem(item, allReleases),
}), [])
);
const flagWithIsNew = (items, allReleases) =>
items.map(
item => ({
...item,
isNew: isNewItem(item, allReleases),
}),
[],
);
const isNewItem = (item, allReleases) => {
return item.revisions.length > 1 && item.revisions[0].release === allReleases[allReleases.length-1]
return (
item.revisions.length === 0 ||
item.revisions[0].release === allReleases[allReleases.length - 1]
);
};

View File

@@ -1,6 +1,7 @@
import React from 'react';
import { formatRelease } from '../date';
import { featuredOnly } from '../../common/model';
import HeroHeadline from './HeroHeadline';
import QuadrantGrid from './QuadrantGrid';
import Fadeable from './Fadeable';
@@ -22,7 +23,7 @@ export default function PageIndex({
AOE Technology Radar
</HeroHeadline>
</div>
<QuadrantGrid items={items} />
<QuadrantGrid items={featuredOnly(items)} />
</Fadeable>
);
}

View File

@@ -1,5 +0,0 @@
---
ring: adopt
---
TODO: Updated text here!

View File

@@ -6,14 +6,14 @@ quadrant: languages-and-frameworks
---
In our backend services we frequently encounter the task to transform data
coming from and uploading to external sources and services.
coming from and uploading to external sources and services.
Building more complex data transformation processes with Akka Actors has proven
very difficult for us in the past.
Seeing this data as a stream of elements could allow to handle them piece by
piece and only keeping as much of the data in-process as can currently be
handled.
handled.
[Akka Streams](http://doc.akka.io/docs/akka/current/scala/stream/index.html) is
a [Reactive Streams](http://www.reactive-streams.org/) implementation that
@@ -31,4 +31,3 @@ more complex services with it.
We will continue looking into it together with the
[Alpakka](/languages-and-frameworks/alpakka.html) Connectors for integration
work.