blob: 973961f5836de32941b536b3b383750faf00e6b1 [file] [log] [blame]
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="keywords" content=" ">
<title>Streaming concepts | Apache Edgent Documentation</title>
<link rel="stylesheet" type="text/css" href="../css/syntax.css">
<link rel="stylesheet" type="text/css" href="../css/font-awesome.min.css">
<!--<link rel="stylesheet" type="text/css" href="../css/bootstrap.min.css">-->
<link rel="stylesheet" type="text/css" href="../css/modern-business.css">
<link rel="stylesheet" type="text/css" href="../css/lavish-bootstrap.css">
<link rel="stylesheet" type="text/css" href="../css/customstyles.css">
<link rel="stylesheet" type="text/css" href="../css/theme-blue.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script src="../js/jquery.navgoco.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/2.0.0/anchor.min.js"></script>
<script src="../js/toc.js"></script>
<script src="../js/customscripts.js"></script>
<link rel="shortcut icon" href="../common_images/favicon.ico" type="image/x-icon">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<script>
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
</script>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container topnavlinks">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="fa fa-home fa-lg navbar-brand" href="../docs/home.html">&nbsp;<span class="projectTitle"> Apache Edgent Documentation</span></a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<!-- entries without drop-downs appear here -->
<!-- conditional logic to control which topnav appears for the audience defined in the configuration file.-->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">GitHub Repos<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="https://github.com/apache/incubator-edgent" target="_blank">Source code</a></li>
<li><a href="https://github.com/apache/incubator-edgent-samples" target="_blank">Edgent Samples</a></li>
<li><a href="https://github.com/apache/incubator-edgent-website" target="_blank">Website/Documentation</a></li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Javadoc<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="..\javadoc\latest">latest</a></li>
<li><a href="..\javadoc\r1.2.0">1.2.0</a></li>
<li><a href="..\javadoc\r1.1.0">1.1.0</a></li>
<li><a href="..\javadoc\r1.0.0">1.0.0</a></li>
<li><a href="..\javadoc\r0.4.0">0.4.0</a></li>
</ul>
</li>
<!-- entries with drop-downs appear here -->
<!-- conditional logic to control which topnav appears for the audience defined in the configuration file.-->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Edgent Resources<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="downloads">Download</a></li>
<li><a href="faq">FAQ</a></li>
<li class="dropdownActive"><a href="/">edgent.apache.org</a></li>
</ul>
</li>
<!-- special insertion -->
<!-- Send feedback function -->
<script>
function SendLinkByMail(href) {
var subject= "Apache Edgent Documentation feedback";
var body = "I have some feedback about the Streaming concepts page: ";
body += window.location.href;
body += "";
var uri = "mailto:?subject=";
uri += encodeURIComponent(subject);
uri += "&body=";
uri += encodeURIComponent(body);
window.location.href = uri;
}
</script>
<li><a href="mailto:dev@edgent.incubator.apache.org" target="_blank"><i class="fa fa-envelope-o"></i> Feedback</a></li>
<!--uncomment this block if you want simple search instead of algolia-->
<li>
<!--start search-->
<div id="search-demo-container">
<input type="text" id="search-input" placeholder="search...">
<ul id="results-container"></ul>
</div>
<script src="../js/jekyll-search.js" type="text/javascript"></script>
<script type="text/javascript">
SimpleJekyllSearch.init({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
dataSource: '../search.json',
searchResultTemplate: '<li><a href="{url}" title="Streaming concepts">{title}</a></li>',
noResultsText: 'No results found.',
limit: 10,
fuzzy: true,
})
</script>
<!--end search-->
</li>
</div>
<!-- /.container -->
</nav>
<!-- Page Content -->
<div class="container">
<div class="col-lg-12">&nbsp;</div>
<!-- Content Row -->
<div class="row">
<!-- Sidebar Column -->
<div class="col-md-3">
<script>
$(document).ready(function() {
// Initialize navgoco with default options
$("#mysidebar").navgoco({
caretHtml: '',
accordion: true,
openClass: 'active', // open
save: true,
cookie: {
name: 'navgoco',
expires: false,
path: '/'
},
slide: {
duration: 400,
easing: 'swing'
}
});
$("#collapseAll").click(function(e) {
e.preventDefault();
$("#mysidebar").navgoco('toggle', false);
});
$("#expandAll").click(function(e) {
e.preventDefault();
$("#mysidebar").navgoco('toggle', true);
});
});
</script>
<ul id="mysidebar" class="nav">
<span class="siteTagline">Edgent</span>
<span class="versionTagline">Version 1.2.0-incubating</span>
<li><a href="#">Overview</a>
<ul>
<li><a href="../docs/edgent_index.html">Introduction</a></li>
<li><a href="../docs/home.html">Edgent Overview</a></li>
<li><a href="../docs/power-of-edgent.html">The Power of Edgent</a></li>
<li><a href="../docs/faq.html">FAQ</a></li>
</ul>
<li><a href="#">Get Started</a>
<ul>
<li><a href="../docs/downloads.html">Downloads</a></li>
<li><a href="../docs/edgent-getting-started.html">Getting Started Guide</a></li>
<li><a href="../docs/edgent-getting-started-samples.html">Quickstart with Edgent Samples</a></li>
<li><a href="../docs/application-development.html">Understanding App Development</a></li>
<li><a href="../docs/quickstart.html">Quickstart IBM Watson IoT Platform</a></li>
<li class="active"><a href="../docs/streaming-concepts.html">Streaming concepts</a></li>
<li><a href="../docs/common-edgent-operations.html">Common operations</a></li>
</ul>
<li><a href="#">Edgent Cookbook</a>
<ul>
<li><a href="../recipes/recipe_hello_edgent.html">Hello Edgent!</a></li>
<li><a href="../recipes/recipe_source_function.html">Writing a source function</a></li>
<li><a href="../recipes/recipe_value_out_of_range.html">Detecting a sensor value out of expected range</a></li>
<li><a href="../recipes/recipe_different_processing_against_stream.html">Applying different processing against a single stream</a></li>
<li><a href="../recipes/recipe_combining_streams_processing_results.html">Splitting a stream to apply different processing and combining the results into a single stream</a></li>
<li><a href="../recipes/recipe_external_filter_range.html">Using an external configuration file for filter ranges</a></li>
<li><a href="../recipes/recipe_adaptable_filter_range.html">Changing a filter's range</a></li>
<li><a href="../recipes/recipe_adaptable_polling_source.html">Changing a polled source stream's period</a></li>
<li><a href="../recipes/recipe_adaptable_deadtime_filter.html">Using an adaptable deadtime filter</a></li>
<li><a href="../recipes/recipe_dynamic_analytic_control.html">Dynamically enabling analytic flows</a></li>
<li><a href="../recipes/recipe_parallel_analytics.html">How can I run analytics on several tuples in parallel?</a></li>
<li><a href="../recipes/recipe_concurrent_analytics.html">How can I run several analytics on a tuple concurrently?</a></li>
<li><a href="../recipes/recipe_writing_a_connector.html">How do I write a connector?</a></li>
</ul>
<li><a href="#">Using the Console</a>
<ul>
<li><a href="../docs/console.html">Using the console</a></li>
</ul>
<li><a href="#">Get Involved</a>
<ul>
<li><a href="../docs/community.html">How to participate</a></li>
<li><a href="../docs/committers.html">Committers</a></li>
</ul>
<!-- if you aren't using the accordion, uncomment this block:
<p class="external">
<a href="#" id="collapseAll">Collapse All</a> | <a href="#" id="expandAll">Expand All</a>
</p>
-->
<br/>
</li>
</ul>
<div class="row">
<div class="col-md-12">
<!-- this handles the automatic toc. use ## for subheads to auto-generate the on-page minitoc. if you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc. -->
<script>
$( document ).ready(function() {
// Handler for .ready() called.
$('#toc').toc({ minimumHeaders: 0, listType: 'ul', showSpeed: 0, headers: 'h2,h3,h4' });
/* this offset helps account for the space taken up by the floating toolbar. */
$('#toc').on('click', 'a', function() {
var target = $(this.getAttribute('href'))
, scroll_target = target.offset().top
$(window).scrollTop(scroll_target - 10);
return false
})
});
</script>
<div id="toc"></div>
</div>
</div>
</div>
<!-- this highlights the active parent class in the navgoco sidebar. this is critical so that the parent expands when you're viewing a page. This must appear below the sidebar code above. Otherwise, if placed inside customscripts.js, the script runs before the sidebar code runs and the class never gets inserted.-->
<script>$("li.active").parents('li').toggleClass("active");</script>
<!-- Content Column -->
<div class="col-md-9">
<div class="post-header">
<h1 class="post-title-main">Streaming concepts</h1>
</div>
<div class="post-content">
<!-- this handles the automatic toc. use ## for subheads to auto-generate the on-page minitoc. if you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc. -->
<script>
$( document ).ready(function() {
// Handler for .ready() called.
$('#toc').toc({ minimumHeaders: 0, listType: 'ul', showSpeed: 0, headers: 'h2,h3,h4' });
/* this offset helps account for the space taken up by the floating toolbar. */
$('#toc').on('click', 'a', function() {
var target = $(this.getAttribute('href'))
, scroll_target = target.offset().top
$(window).scrollTop(scroll_target - 10);
return false
})
});
</script>
<div id="toc"></div>
<a target="_blank" href="https://github.com/apache/incubator-edgent-website/blob/master/site/docs/streaming-concepts.md" class="btn btn-default githubEditButton" role="button"><i class="fa fa-github fa-lg"></i> Edit me</a>
<p>An Edgent application is most useful when processing some sort of data. This page is intended to help you understand stream processing concepts by visually demonstrating some of the operations that can be invoked on a stream, along with code snippets. For example,</p>
<ul>
<li><a href="/javadoc/latest/org/apache/edgent/topology/TStream.html#filter-org.apache.edgent.function.Predicate-">filter</a></li>
<li><a href="/javadoc/latest/org/apache/edgent/topology/TStream.html#split-int-org.apache.edgent.function.ToIntFunction-">split</a></li>
<li><a href="/javadoc/latest/org/apache/edgent/topology/TStream.html#union-org.apache.edgent.topology.TStream-">union</a></li>
<li><a href="/javadoc/latest/org/apache/edgent/topology/TStream.html#last-long-java.util.concurrent.TimeUnit-org.apache.edgent.function.Function-">partitioned window</a></li>
<li><a href="/javadoc/latest/org/apache/edgent/topology/TWindow.html#aggregate-org.apache.edgent.function.BiFunction-">continuous aggregation</a></li>
<li><a href="/javadoc/latest/org/apache/edgent/topology/TWindow.html#batch-org.apache.edgent.function.BiFunction-">batch</a></li>
</ul>
<h2 id="filter">Filter</h2>
<div id="filter-demo"></div>
<style>
div#filter-demo {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
</style>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var filterSvgContainer = d3.select("#filter-demo").append("svg")
.attr("width", 550)
.attr("height", 200);
var filter = filterSvgContainer.append("circle")
.attr("cx", 300)
.attr("cy", 115)
.attr("r", 50)
.style("fill", "#286DA8");
var filterTxt = filterSvgContainer.append("svg:text")
.attr("x", 275)
.attr("y", 105)
.attr("dx", 25)
.attr("dy", "1.0em")
.attr("text-anchor", "middle")
.text(function(datum) { return "≥ 5"; })
.attr("fill", "white");
function newIncomingFilterTuple() {
var newFilterTuple = filterSvgContainer.append("rect")
.attr("x", 30)
.attr("y", 100)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#CD5360");
var filterTv = Math.floor(Math.random() * 10);
var newFilterTxt = filterSvgContainer.append("svg:text")
.attr("x", 30)
.attr("y", 100)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return filterTv; })
.attr("fill", "white");
newFilterTxt.tv = filterTv;
newFilterTuple.transition().ease("linear").attr("x", 250).duration(6000).delay(100).remove();
newFilterTxt.transition().ease("linear").attr("x", 250).duration(6000).delay(100).remove().each('end',function(){ if (newFilterTxt.tv >= 5) { filteredTuple(newFilterTxt.tv); }});
setTimeout(function() { newIncomingFilterTuple();} , 1200 + (Math.random() * 1000));
}
function filteredTuple(tv) {
var filterTuple = filterSvgContainer.append("rect")
.attr("x", 318)
.attr("y", 100)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#57BC90");
var filterTxt = filterSvgContainer.append("svg:text")
.attr("x", 318)
.attr("y", 100)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return tv; })
.attr("fill", "white");
filterTxt.tv = tv;
filterTuple.transition().ease("linear").attr("x", 520).duration(5500).delay(100).remove();
filterTxt.transition().ease("linear").attr("x", 520).duration(5500).delay(100).remove();
}
newIncomingFilterTuple();
</script>
<h3 id="edgent-code">Edgent code</h3>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">TStream</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span> <span class="n">filtered</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">t</span> <span class="o">-&gt;</span> <span class="n">t</span> <span class="o">&gt;=</span> <span class="mi">5</span><span class="o">);</span>
</code></pre></div>
<h3 id="explanation">Explanation</h3>
<p><strong>Input stream</strong>: Tuples, such as sensor readings, are continually produced and represented as a red stream on the left.</p>
<p><strong>Filtered stream</strong>: A filter operation of <code>t &gt;= 5</code> is applied, resulting in a green output stream on the right that contains tuples with values greater than or equal to five.</p>
<hr>
<h2 id="split">Split</h2>
<div id="split-demo"></div>
<style>
div#split-demo {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
</style>
<script>
var splitSvgContainer = d3.select("#split-demo").append("svg")
.attr("width", 700)
.attr("height", 200);
var split = splitSvgContainer.append("rect")
.attr("x", 250)
.attr("y", 65)
.attr("width", 100)
.attr("height", 100)
.style("fill", "#286DA8");
var splitTxt = splitSvgContainer.append("svg:text")
.attr("x", 275)
.attr("y", 105)
.attr("dx", 25)
.attr("dy", "1.0em")
.attr("text-anchor", "middle")
.text(function(datum) { return "getVal( )"; })
.attr("fill", "white");
var evenTxtMsg = splitSvgContainer.append("svg:text")
.attr("x", 375)
.attr("y", 50)
.attr("dx", 25)
.attr("dy", "1.0em")
.attr("text-anchor", "middle")
.text(function(datum) { return "EVEN"; })
.attr("fill", "#57BC90");
var oddTxtMsg = splitSvgContainer.append("svg:text")
.attr("x", 375)
.attr("y", 165)
.attr("dx", 25)
.attr("dy", "1.0em")
.attr("text-anchor", "middle")
.text(function(datum) { return "ODD"; })
.attr("fill", "#8066B3");
function newIncomingSplitTuple() {
var newSplitTuple = splitSvgContainer.append("rect")
.attr("x", 30)
.attr("y", 100)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#CD5360");
var splitTv = Math.floor(Math.random() * 10);
var newSplitTxt = splitSvgContainer.append("svg:text")
.attr("x", 30)
.attr("y", 100)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return splitTv; })
.attr("fill", "white");
newSplitTxt.tv = splitTv;
newSplitTuple.transition().ease("linear").attr("x", 225).duration(6000).delay(100).remove();
newSplitTxt.transition().ease("linear").attr("x", 225).duration(6000).delay(100).remove().each('end',function(){ if (newSplitTxt.tv % 2 == 0) { splittedEvenTuple(newSplitTxt.tv); } else { splittedOddTuple(newSplitTxt.tv); } });
setTimeout(function() { newIncomingSplitTuple();} , 1200 + (Math.random() * 1000));
}
function splittedEvenTuple(tv) {
var evenTuple = splitSvgContainer.append("rect")
.attr("x", 425)
.attr("y", 45)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#57BC90");
var evenTxt = splitSvgContainer.append("svg:text")
.attr("x", 425)
.attr("y", 45)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return tv; })
.attr("fill", "white");
evenTxt.tv = tv;
evenTuple.transition().ease("linear").attr("x", 670).duration(5500).delay(100).remove();
evenTxt.transition().ease("linear").attr("x", 670).duration(5500).delay(100).remove();
}
function splittedOddTuple(tv) {
var oddTuple = splitSvgContainer.append("rect")
.attr("x", 425)
.attr("y", 160)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#8066B3");
var oddTxt = splitSvgContainer.append("svg:text")
.attr("x", 425)
.attr("y", 160)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return tv; })
.attr("fill", "white");
oddTxt.tv = tv;
oddTuple.transition().ease("linear").attr("x", 670).duration(5500).delay(100).remove();
oddTxt.transition().ease("linear").attr("x", 670).duration(5500).delay(100).remove();
}
newIncomingSplitTuple();
</script>
<h3 id="edgent-code">Edgent code</h3>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">List</span><span class="o">&lt;</span><span class="n">TStream</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;&gt;</span> <span class="n">streams</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">tuple</span> <span class="o">-&gt;</span> <span class="n">tuple</span><span class="o">.</span><span class="na">getVal</span><span class="o">());</span>
</code></pre></div>
<h3 id="explanation">Explanation</h3>
<p><strong>Input streams</strong>: Tuples, such as sensor readings, are continually produced and represented as a red stream on the left.</p>
<p><strong>Split streams</strong>: A split operation of <code>getVal()</code> is applied, resulting in two output streams on the right, one green and one purple. The green stream contains tuples with values that are even integers, while the purple stream contains tuples with values that are odd integers.</p>
<hr>
<h2 id="union">Union</h2>
<div id="union-demo"></div>
<style>
div#union-demo {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
</style>
<script>
var unionSvgContainer = d3.select("#union-demo").append("svg")
.attr("width", 700)
.attr("height", 200);
var union = unionSvgContainer.append("rect")
.attr("x", 250)
.attr("y", 25)
.attr("width", 100)
.attr("height", 150)
.style("fill", "#286DA8");
var unionTxt = unionSvgContainer.append("svg:text")
.attr("x", 275)
.attr("y", 88)
.attr("dx", 25)
.attr("dy", "1.0em")
.attr("text-anchor", "middle")
.text(function(datum) { return "Union"; })
.attr("fill", "white");
function newIncomingStream1Tuple() {
var newstream1Tuple = unionSvgContainer.append("rect")
.attr("x", 30)
.attr("y", 35)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#CD5360");
var stream1Tv = Math.floor(Math.random() * 10);
var newStream1Txt = unionSvgContainer.append("svg:text")
.attr("x", 30)
.attr("y", 35)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return stream1Tv; })
.attr("fill", "white");
newStream1Txt.tv = stream1Tv;
newstream1Tuple.transition().ease("linear").attr("x", 235).duration(6000).delay(100).remove();
newStream1Txt.transition().ease("linear").attr("x", 235).duration(6000).delay(100).remove().each('end',function(){ unionedTuple(newStream1Txt.tv); });
setTimeout(function() { newIncomingStream1Tuple(); } , 1200 + (Math.random() * 2000));
}
function newIncomingStream2Tuple() {
var newstream2Tuple = unionSvgContainer.append("rect")
.attr("x", 30)
.attr("y", 135)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#57BC90");
var stream2Tv = Math.floor(Math.random() * 10);
var newStream2Txt = unionSvgContainer.append("svg:text")
.attr("x", 30)
.attr("y", 135)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return stream2Tv; })
.attr("fill", "white");
newStream2Txt.tv = stream2Tv;
newstream2Tuple.transition().ease("linear").attr("x", 235).duration(6000).delay(100).remove();
newStream2Txt.transition().ease("linear").attr("x", 235).duration(6000).delay(100).remove().each('end',function(){ unionedTuple(newStream2Txt.tv); });
setTimeout(function() { newIncomingStream2Tuple(); } , 2000 + (Math.random() * 2000));
}
function unionedTuple(tv) {
var unionTuple = unionSvgContainer.append("rect")
.attr("x", 328)
.attr("y", 85)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#8066B3");
var unionTxt = unionSvgContainer.append("svg:text")
.attr("x", 328)
.attr("y", 85)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return tv; })
.attr("fill", "white");
unionTxt.tv = tv;
unionTuple.transition().ease("linear").attr("x", 670).duration(5500).delay(100).remove();
unionTxt.transition().ease("linear").attr("x", 670).duration(5500).delay(100).remove();
}
newIncomingStream1Tuple();
setTimeout(function() { newIncomingStream2Tuple(); }, 1000);
</script>
<h3 id="edgent-code">Edgent code</h3>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">TStream</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="n">stream</span> <span class="o">=</span> <span class="n">stream1</span><span class="o">.</span><span class="na">union</span><span class="o">(</span><span class="n">stream2</span><span class="o">);</span>
</code></pre></div>
<h3 id="explanation">Explanation</h3>
<p><strong>Input streams</strong>: Tuples, such as sensor readings, are continually produced on two different streams, represented as a red stream and a green stream on the left.</p>
<p><strong>Unioned stream</strong>: A union operation is applied, resulting in a single purple output stream on the right. The stream contains tuples from both input streams.</p>
<hr>
<h2 id="window-last-5-seconds">Window (last 5 seconds)</h2>
<div id="window-demo"></div>
<style>
div#window-demo {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
</style>
<script>
var xt = 250;
var xs = 30;
var windowSvgContainer = d3.select("#window-demo").append("svg")
.attr("width", 840)
.attr("height", 200);
var streamWindow = windowSvgContainer.append("rect")
.attr("x", 300)
.attr("y", 75)
.attr("width", 370/2+45)
.attr("height", 80)
.style("stroke", "#286DA8")
.style("fill", "none")
.style("stroke-width", "3px");
function newIncomingWindowTuple() {
var newWindowTuple = windowSvgContainer.append("rect")
.attr("x", xs)
.attr("y", 100)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#CD5360");
var windowTv = Math.floor(Math.random() * 10);
var newWindowTxt = windowSvgContainer.append("svg:text")
.attr("x", xs)
.attr("y", 100)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return windowTv; })
.attr("fill", "white");
newWindowTxt.tv = windowTv;
newWindowTuple.transition().ease("linear").attr("x", xs + xt).duration(6000).delay(100).remove();
newWindowTxt.transition().ease("linear").attr("x", xs + xt).duration(6000).delay(100).remove().each('end',function(){ windowedTuple(newWindowTxt.tv); });
setTimeout(function() { newIncomingWindowTuple();} , 1200 + (Math.random() * 1000));
}
var wxs = 310;
function windowedTuple(tv) {
var windowTuple = windowSvgContainer.append("rect")
.attr("x", wxs)
.attr("y", 100)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#57BC90");
var windowTxt = windowSvgContainer.append("svg:text")
.attr("x", wxs)
.attr("y", 100)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return tv; })
.attr("fill", "white");
windowTxt.tv = tv;
windowTuple.transition().ease("linear").attr("x", wxs + (370/2)).duration(5000).delay(100).remove();
windowTxt.transition().ease("linear").attr("x", wxs + (370/2)).duration(5000).delay(100).remove();
}
newIncomingWindowTuple();
</script>
<h3 id="edgent-code">Edgent code</h3>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">TWindow</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span> <span class="n">window</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">last</span><span class="o">(</span><span class="mi">5</span><span class="o">,</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">,</span> <span class="n">tuple</span> <span class="o">-&gt;</span> <span class="mi">0</span><span class="o">);</span>
</code></pre></div>
<h3 id="explanation">Explanation</h3>
<p><strong>Input stream</strong>: Tuples, such as sensor readings, are continually produced and represented as a red stream on the left.</p>
<p><strong>Window</strong>: A window declaration of the last five seconds of tuples results in the window outlined in blue containing green tuples. A tuple is inserted into the window when it appears on the stream and is evicted five seconds later, since it will have been in the window for five seconds at that point.</p>
<hr>
<h2 id="continuous-aggregate-max-last-5-seconds">Continuous aggregate (max, last 5 seconds)</h2>
<div id="agg-demo"></div>
<style>
div#agg-demo {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
</style>
<script>
var xt = 250;
var xs = 30;
var aggSvgContainer = d3.select("div#agg-demo").append("svg")
.attr("width", 800)
.attr("height", 200);
var aggWindow = aggSvgContainer.append("rect")
.attr("x", 300)
.attr("y", 75)
.attr("width", 370/2+45)
.attr("height", 80)
.style("stroke", "#286DA8")
.style("fill", "none")
.style("stroke-width", "3px");
var MaxTxt = aggSvgContainer.append("svg:text")
.attr("x", 480)
.attr("y", 165)
.attr("dx", 25)
.attr("dy", "1.0em")
.attr("text-anchor", "middle")
.text(function(datum) { return "MAX"; })
.attr("fill", "#8066B3");
function newIncomingAggTuple() {
var newAggTuple = aggSvgContainer.append("rect")
.attr("x", xs)
.attr("y", 100)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#CD5360");
var aggTv = Math.floor(Math.random() * 10);
var newAggTxt = aggSvgContainer.append("svg:text")
.attr("x", xs)
.attr("y", 100)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return aggTv; })
.attr("fill", "white");
newAggTxt.tv = aggTv;
newAggTuple.transition().ease("linear").attr("x", xs + xt).duration(6000).delay(100).remove();
newAggTxt.transition().ease("linear").attr("x", xs + xt).duration(6000).delay(100).remove().each('end',function() { windowedAggTuple(newAggTxt.tv); });
setTimeout(function() { newIncomingAggTuple();} , 1200 + (Math.random() * 1000));
}
var aggWin = [];
function addToAggWindow(v) {
aggWin.push(v);
aggregate();
}
function evictFromAggWindow() {
aggWin.shift();
aggregate();
}
var wxs = 310;
function windowedAggTuple(tv) {
addToAggWindow(tv);
var windowAggTuple = aggSvgContainer.append("rect")
.attr("x", wxs)
.attr("y", 100)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#57BC90");
var windowAggTxt = aggSvgContainer.append("svg:text")
.attr("x", wxs)
.attr("y", 100)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return tv; })
.attr("fill", "white");
windowAggTxt.tv = tv;
windowAggTuple.transition().ease("linear").attr("x", wxs + (370/2)).duration(5000).delay(100).remove();
windowAggTxt.transition().ease("linear").attr("x", wxs + (370/2)).duration(5000).delay(100).remove().each('end', function() {evictFromAggWindow()});
}
function aggregate() {
var maxW = Math.max.apply(Math, aggWin);
var aggTuple = aggSvgContainer.append("rect")
.attr("x", 530)
.attr("y", 160)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#8066B3");
var txtMax = aggSvgContainer.append("svg:text")
.attr("x", 530)
.attr("y", 160)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return maxW; })
.attr("fill", "white");
aggTuple.transition().ease("linear").attr("x", 770).duration(5000).delay(100).remove();
txtMax.transition().ease("linear").attr("x", 770).duration(5000).delay(100).remove();
}
newIncomingAggTuple();
</script>
<h3 id="edgent-code">Edgent code</h3>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">TWindow</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span> <span class="n">window</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">last</span><span class="o">(</span><span class="mi">5</span><span class="o">,</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">,</span> <span class="n">tuple</span> <span class="o">-&gt;</span> <span class="mi">0</span><span class="o">);</span>
<span class="n">TStream</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span> <span class="n">max</span> <span class="o">=</span> <span class="n">window</span><span class="o">.</span><span class="na">aggregate</span><span class="o">((</span><span class="n">tuples</span><span class="o">,</span> <span class="n">key</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">Collections</span><span class="o">.</span><span class="na">max</span><span class="o">(</span><span class="n">tuples</span><span class="o">);</span>
<span class="o">});</span>
</code></pre></div>
<h3 id="explanation">Explanation</h3>
<p><strong>Input stream</strong>: Tuples, such as sensor readings, are continually produced and represented as a red stream on the left.</p>
<p><strong>Window</strong>: A window declaration of the last five seconds of tuples results in the window outlined in blue containing green tuples. A tuple is inserted into the window when it appears on the stream and is evicted five seconds later, since it will have been in the window for five seconds at that point.</p>
<p><strong>Aggregation</strong>: The window is <em>continuously</em> aggregated to find the maximum value in the window. <em>Continuously aggregated</em> means that every time the window contents changes, the aggregate is calculated and a tuple is produced on the purple output stream. The window changes every time a tuple is inserted or evicted, where time-based window insertions and evictions are independent events.</p>
<hr>
<h2 id="batch-size-last-5-seconds">Batch (size, last 5 seconds)</h2>
<div id="batch-demo"></div>
<style>
div#agg-demo {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
</style>
<script>
var xt = 250;
var xs = 30;
var batchSvgContainer = d3.select("div#batch-demo").append("svg")
.attr("width", 800)
.attr("height", 200);
var batchWindow = batchSvgContainer.append("rect")
.attr("x", 300)
.attr("y", 75)
.attr("width", 370/2+45)
.attr("height", 80)
.style("stroke", "#286DA8")
.style("fill", "none")
.style("stroke-width", "3px");
var SizeTxt = batchSvgContainer.append("svg:text")
.attr("x", 480)
.attr("y", 165)
.attr("dx", 25)
.attr("dy", "1.0em")
.attr("text-anchor", "middle")
.text(function(datum) { return "SIZE"; })
.attr("fill", "#8066B3");
function newIncomingBatchTuple() {
var newBatchTuple = batchSvgContainer.append("rect")
.attr("x", xs)
.attr("y", 100)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#CD5360");
var batchTv = Math.floor(Math.random() * 10);
var newBatchTxt = batchSvgContainer.append("svg:text")
.attr("x", xs)
.attr("y", 100)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return batchTv; })
.attr("fill", "white");
newBatchTxt.tv = batchTv;
newBatchTuple.transition().ease("linear").attr("x", xs + xt).duration(6000).delay(100).remove();
newBatchTxt.transition().ease("linear").attr("x", xs + xt).duration(6000).delay(100).remove().each('end',function() { windowedBatchTuple(newBatchTxt.tv); });
setTimeout(function() { newIncomingBatchTuple();} , 1200 + (Math.random() * 1000));
}
var batchWin = [];
// timer
var initialStart = 0;
var timer = 0;
function run() {
timer++;
if (timer == 5) {
console.log("5 seconds elapsed");
timer = 0;
batch();
}
}
function addToBatchWindow(v) {
batchWin.push(v);
if (initialStart == 0) {
initialStart = 1;
setInterval(run, 1000);
}
}
function evictFromBatchWindow() {
batchWin.shift();
}
var wxs = 310;
function windowedBatchTuple(tv) {
addToBatchWindow(tv);
var windowBatchTuple = batchSvgContainer.append("rect")
.attr("x", wxs)
.attr("y", 100)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#57BC90");
var windowBatchTxt = batchSvgContainer.append("svg:text")
.attr("x", wxs)
.attr("y", 100)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return tv; })
.attr("fill", "white");
windowBatchTxt.tv = tv;
windowBatchTuple.transition().ease("linear").attr("x", wxs + (370/2)).duration(5000).delay(100).remove();
windowBatchTxt.transition().ease("linear").attr("x", wxs + (370/2)).duration(5000).delay(100).remove().each('end', function() {evictFromBatchWindow()});
}
function batch() {
var sizeW = batchWin.length;
console.log("window size: " + sizeW);
var sizeTuple = batchSvgContainer.append("rect")
.attr("x", 530)
.attr("y", 160)
.attr("width", 30)
.attr("height", 30)
.style("fill", "#8066B3");
var txtSize = batchSvgContainer.append("svg:text")
.attr("x", 530)
.attr("y", 160)
.attr("dx", 15.5)
.attr("dy", 20)
.attr("text-anchor", "middle")
.text(function(datum) { return sizeW; })
.attr("fill", "white");
sizeTuple.transition().ease("linear").attr("x", 770).duration(5000).delay(100).remove();
txtSize.transition().ease("linear").attr("x", 770).duration(5000).delay(100).remove();
}
newIncomingBatchTuple();
</script>
<h3 id="edgent-code">Edgent code</h3>
<div class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">TWindow</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span> <span class="n">window</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">last</span><span class="o">(</span><span class="mi">5</span><span class="o">,</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">,</span> <span class="n">tuple</span> <span class="o">-&gt;</span> <span class="mi">0</span><span class="o">);</span>
<span class="n">TStream</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">&gt;</span> <span class="n">size</span> <span class="o">=</span> <span class="n">window</span><span class="o">.</span><span class="na">batch</span><span class="o">((</span><span class="n">tuples</span><span class="o">,</span> <span class="n">key</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">tuples</span><span class="o">.</span><span class="na">size</span><span class="o">();</span>
<span class="o">});</span>
</code></pre></div>
<h3 id="explanation">Explanation</h3>
<p><strong>Input stream</strong>: Tuples, such as sensor readings, are continually produced and represented as a red stream on the left.</p>
<p><strong>Window</strong>: A window declaration of the last five seconds of tuples results in the window outlined in blue containing green tuples. A tuple is inserted into the window when it appears on the stream and is evicted five seconds later, since it will have been in the window for five seconds at that point.</p>
<p><strong>Batch</strong>: The window is batched to find the number of tuples in the window. A <em>batch</em> means that every 5 seconds, the size of the window is calculated and a tuple is produced on the purple output stream.</p>
<div class="tags">
</div>
<!--
<div id="disqus_thread"></div>
<script type="text/javascript">
/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
var disqus_shortname = 'idrbwjekyll'; // required: replace example with your forum shortname
/* * * DON'T EDIT BELOW THIS LINE * * */
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
-->
</div>
<footer>
<div class="row">
<div class="col-lg-12 footer">
Site last
generated: Dec 18, 2017 <br/>
</div>
</div>
<br/>
<div class="row">
<div class="col-md-12">
<p class="small">Apache Edgent is an effort undergoing Incubation at The Apache Software
Foundation (ASF), sponsored by the Incubator. Incubation is required of all newly accepted projects
until a further review indicates that the infrastructure, communications, and decision making process
have stabilized in a manner consistent with other successful ASF projects. While incubation status is
not necessarily a reflection of the completeness or stability of the code, it does indicate that the
project has yet to be fully endorsed by the ASF.</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p class="small">Copyright © 2016 The Apache Software Foundation. Licensed under the Apache
License, Version 2.0.
Apache, the Apache Feather logo, and the Apache Incubator project logo are trademarks of The Apache
Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their
respective owners.</p>
</div>
</div>
<div class="container">
<div class="row">
<div>
<img class="img-responsive center-block" src="../img/edgent_incubation.png" style="display: block; margin: auto;"alt="">
</div>
</div>
</footer>
</div><!-- /.row -->
</div> <!-- /.container -->
</body>
</html>