Artem Arkhipov
Lead Web Developer at Techmagic
@ar_arkhipov
artem.arkhipov@techmagic.co
.cloud
.cloud
What is
?
.cloud
What is
?
.cloud
IS NOT about drawing only
.cloud
main technology stack:
And few third party services...
Transform this:
To this:
1. Do it on client side and send directly to S3
2. Use jGraph server ( Java )
3. We should find serverless solution (FaaS)
4. Send diagram HTML and render it to image with PhantomJS or similar tools
5. Load whole Diagram Editor in PhantomJS or Selenium and capture screenshot
Write main handler functions:
Run headless chrome inside AWS Lambda
- Launch chrome as child process
- Open virtual tabs with diagrams
- Wait till diagrams are loaded
- Capture screenshots
- Save screenshots to AWS S3
- Close tabs
- Trigger image-resizing Lambda via SNS
Create lighter Diagram Editor version
Make "delayed lambda invocation" mechanism
const CHROME_URL = 'http://127.0.0.1:9222';
const CHROME_FLAGS = [
'--headless',
'--disable-gpu',
'--remote-debugging-port=9222',
'--window-size=1200,800',
'--no-sandbox',
'--user-data-dir=/tmp/user-data',
'--hide-scrollbars',
'--enable-logging',
'--log-level=0',
'--v=99',
'--single-process',
'--data-path=/tmp/data-path',
'--ignore-certificate-errors',
'--homedir=/tmp',
'--disk-cache-dir=/tmp/cache-dir'
];const spawn = require('child_process').spawn;
let chrome;
function spawnChrome() {
console.log('Spawning Chrome...');
chrome = spawn(__dirname+'/headless-chrome/headless_shell',
config.CHROME_FLAGS, {
cwd: '/tmp',
shell: true,
detached: true,
stdio: 'ignore'
});
chrome.unref();
chrome.on('close', (code) => {
console.log('Chrome closed with code: ', code);
chrome = null;
spawnChrome();
});
}const CDP = require('chrome-remote-interface');
function openTab() {
return CDP.New().then((tab) => { //create tab
return CDP({tab}).then((client) => { //create client
return Promise.all([
client.Page.enable(),
client.Runtime.enable()
]).then(() => {
return Promise.resolve({client}); //ready
})
})
})
}const Promise = require('bluebird');
function navigate({url}) {
return new Promise((resolve, reject) => {
// setup any events or conditions
client.Page.loadEventFired(() => resolve())
//run navigation to page
client.Page.navigate({url});
}).timeout(config.LOAD_TIMEOUT);
}function capture({client}) {
return client.Page.captureScreenshot({
fromSurface: true,
format: 'png'
}).then((screenshot) => {
client.close();
const image = screenshot.data;
return Promise.resolve({image});
})
}function closeTabs() {
console.log('Cleaning opened tabs...');
return CDP.List().then((tabs) => {
return Promise.all(tabs.map(({id}) => CDP.Close({id})))
})
}Scalable and reliable
Execution time about 1 - 2.5s
160 000 images cost less than ~10$ (AWS free tier is not included!)
Artem Arkhipov
Lead Web Developer at Techmagic
@ar_arkhipov
ar.arkhipov@gmail.com
Thank You!
artem.arkhipov@techmagic.co