blob: 8d8d69ebffa8ee24b745216ef5a70cfe82cf1ae5 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en" dir=ZgotmplZ>
<head>
<link rel="stylesheet" href="/bootstrap/css/bootstrap.min.css">
<script src="/bootstrap/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" type="text/css" href="/font-awesome/css/font-awesome.min.css">
<script src="/js/anchor.min.js"></script>
<script src="/js/flink.js"></script>
<link rel="canonical" href="https://flink.apache.org/2021/08/31/stateful-functions-3.1.0-release-announcement/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Stateful Functions is a cross-platform stack for building Stateful Serverless applications, making it radically simpler to develop scalable, consistent, and elastic distributed applications. This new release brings various improvements to the StateFun runtime, a leaner way to specify StateFun module components, and a brand new GoLang SDK!
The binary distribution and source artifacts are now available on the updated Downloads page of the Flink website, and the most recent Java SDK, Python SDK, and GoLang SDK distributions are available on Maven, PyPI, and Github repecitvely.">
<meta name="theme-color" content="#FFFFFF"><meta property="og:title" content="Stateful Functions 3.1.0 Release Announcement" />
<meta property="og:description" content="Stateful Functions is a cross-platform stack for building Stateful Serverless applications, making it radically simpler to develop scalable, consistent, and elastic distributed applications. This new release brings various improvements to the StateFun runtime, a leaner way to specify StateFun module components, and a brand new GoLang SDK!
The binary distribution and source artifacts are now available on the updated Downloads page of the Flink website, and the most recent Java SDK, Python SDK, and GoLang SDK distributions are available on Maven, PyPI, and Github repecitvely." />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://flink.apache.org/2021/08/31/stateful-functions-3.1.0-release-announcement/" /><meta property="article:section" content="posts" />
<meta property="article:published_time" content="2021-08-31T08:00:00+00:00" />
<meta property="article:modified_time" content="2021-08-31T08:00:00+00:00" />
<title>Stateful Functions 3.1.0 Release Announcement | Apache Flink</title>
<link rel="manifest" href="/manifest.json">
<link rel="icon" href="/favicon.png" type="image/x-icon">
<link rel="stylesheet" href="/book.min.22eceb4d17baa9cdc0f57345edd6f215a40474022dfee39b63befb5fb3c596b5.css" integrity="sha256-IuzrTRe6qc3A9XNF7dbyFaQEdAIt/uObY777X7PFlrU=">
<script defer src="/en.search.min.2698f0d1b683dae4d6cb071668b310a55ebcf1c48d11410a015a51d90105b53e.js" integrity="sha256-Jpjw0baD2uTWywcWaLMQpV688cSNEUEKAVpR2QEFtT4="></script>
<!--
Made with Book Theme
https://github.com/alex-shpak/hugo-book
-->
<meta name="generator" content="Hugo 0.124.1">
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['disableCookies']);
_paq.push(["setDomains", ["*.flink.apache.org","*.nightlies.apache.org/flink"]]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
</head>
<body dir=ZgotmplZ>
<header>
<nav class="navbar navbar-expand-xl">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img src="/img/logo/png/100/flink_squirrel_100_color.png" alt="Apache Flink" height="47" width="47" class="d-inline-block align-text-middle">
<span>Apache Flink</span>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<i class="fa fa-bars navbar-toggler-icon"></i>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">About</a>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="/what-is-flink/flink-architecture/">Architecture</a>
</li>
<li>
<a class="dropdown-item" href="/what-is-flink/flink-applications/">Applications</a>
</li>
<li>
<a class="dropdown-item" href="/what-is-flink/flink-operations/">Operations</a>
</li>
<li>
<a class="dropdown-item" href="/what-is-flink/use-cases/">Use Cases</a>
</li>
<li>
<a class="dropdown-item" href="/what-is-flink/powered-by/">Powered By</a>
</li>
<li>
<a class="dropdown-item" href="/what-is-flink/roadmap/">Roadmap</a>
</li>
<li>
<a class="dropdown-item" href="/what-is-flink/community/">Community & Project Info</a>
</li>
<li>
<a class="dropdown-item" href="/what-is-flink/security/">Security</a>
</li>
<li>
<a class="dropdown-item" href="/what-is-flink/special-thanks/">Special Thanks</a>
</li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Getting Started</a>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-docs-stable/docs/try-flink/local_installation/">With Flink<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-kubernetes-operator-docs-stable/docs/try-flink-kubernetes-operator/quick-start/">With Flink Kubernetes Operator<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-cdc-docs-stable/docs/get-started/introduction/">With Flink CDC<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-ml-docs-stable/docs/try-flink-ml/quick-start/">With Flink ML<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-statefun-docs-stable/getting-started/project-setup.html">With Flink Stateful Functions<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-docs-stable/docs/learn-flink/overview/">Training Course<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Documentation</a>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-docs-stable/">Flink 1.19 (stable)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-docs-master/">Flink Master (snapshot)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-kubernetes-operator-docs-stable/">Kubernetes Operator 1.8 (latest)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-kubernetes-operator-docs-main">Kubernetes Operator Main (snapshot)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-cdc-docs-stable">CDC 3.0 (stable)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-cdc-docs-master">CDC Master (snapshot)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-ml-docs-stable/">ML 2.3 (stable)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-ml-docs-master">ML Master (snapshot)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-statefun-docs-stable/">Stateful Functions 3.3 (stable)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
<li>
<a class="dropdown-item" href="https://nightlies.apache.org/flink/flink-statefun-docs-master">Stateful Functions Master (snapshot)<i class="link fa fa-external-link title" aria-hidden="true"></i>
</a>
</li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">How to Contribute</a>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="/how-to-contribute/overview/">Overview</a>
</li>
<li>
<a class="dropdown-item" href="/how-to-contribute/contribute-code/">Contribute Code</a>
</li>
<li>
<a class="dropdown-item" href="/how-to-contribute/reviewing-prs/">Review Pull Requests</a>
</li>
<li>
<a class="dropdown-item" href="/how-to-contribute/code-style-and-quality-preamble/">Code Style and Quality Guide</a>
</li>
<li>
<a class="dropdown-item" href="/how-to-contribute/contribute-documentation/">Contribute Documentation</a>
</li>
<li>
<a class="dropdown-item" href="/how-to-contribute/documentation-style-guide/">Documentation Style Guide</a>
</li>
<li>
<a class="dropdown-item" href="/how-to-contribute/improve-website/">Contribute to the Website</a>
</li>
<li>
<a class="dropdown-item" href="/how-to-contribute/getting-help/">Getting Help</a>
</li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link" href="/posts/">Flink Blog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/downloads/">Downloads</a>
</li>
</ul>
<div class="book-search">
<div class="book-search-spinner hidden">
<i class="fa fa-refresh fa-spin"></i>
</div>
<form class="search-bar d-flex" onsubmit="return false;"su>
<input type="text" id="book-search-input" placeholder="Search" aria-label="Search" maxlength="64" data-hotkeys="s/">
<i class="fa fa-search search"></i>
<i class="fa fa-circle-o-notch fa-spin spinner"></i>
</form>
<div class="book-search-spinner hidden"></div>
<ul id="book-search-results"></ul>
</div>
</div>
</div>
</nav>
<div class="navbar-clearfix"></div>
</header>
<main class="flex">
<section class="container book-page">
<article class="markdown">
<h1>
<a href="/2021/08/31/stateful-functions-3.1.0-release-announcement/">Stateful Functions 3.1.0 Release Announcement</a>
</h1>
August 31, 2021 -
Seth Wiesman
<a href="https://twitter.com/sjwiesman">(@sjwiesman)</a>
Igal Shilman
<a href="https://twitter.com/IgalShilman">(@IgalShilman)</a>
Tzu-Li (Gordon) Tai
<a href="https://twitter.com/tzulitai">(@tzulitai)</a>
<p><p>Stateful Functions is a cross-platform stack for building Stateful Serverless applications, making it radically simpler to develop scalable, consistent, and elastic distributed applications.
This new release brings various improvements to the StateFun runtime, a leaner way to specify StateFun module components, and a brand new GoLang SDK!</p>
<p>The binary distribution and source artifacts are now available on the updated <a href="https://flink.apache.org/downloads.html">Downloads</a>
page of the Flink website, and the most recent Java SDK, Python SDK, and GoLang SDK distributions are available on <a href="https://search.maven.org/artifact/org.apache.flink/statefun-sdk-java/3.1.0/jar">Maven</a>, <a href="https://pypi.org/project/apache-flink-statefun/">PyPI</a>, and <a href="https://github.com/apache/flink-statefun/tree/statefun-sdk-go/v3.1.0">Github</a> repecitvely.
You can also find official StateFun Docker images of the new version on <a href="https://hub.docker.com/r/apache/flink-statefun">Dockerhub</a>.</p>
<p>For more details, check the complete <a href="https://issues.apache.org/jira/secure/ReleaseNote.jspa?version=12350038&amp;projectId=12315522">release changelog</a>
and the <a href="//nightlies.apache.org/flink/flink-statefun-docs-release-3.0/">updated documentation</a>.
We encourage you to download the release and share your feedback with the community through the <a href="https://flink.apache.org/community.html#mailing-lists">Flink mailing lists</a>
or <a href="https://issues.apache.org/jira/browse/">JIRA</a>!</p>
<h2 id="new-features">
New Features
<a class="anchor" href="#new-features">#</a>
</h2>
<h3 id="delayed-message-cancellation">
Delayed Message Cancellation
<a class="anchor" href="#delayed-message-cancellation">#</a>
</h3>
<p>Stateful Functions communicate by sending messages, but sometimes it is helpful that a function will send a message for itself.
For example, you may want to set a time limit on a customer onboarding flow to complete.
This can easily be implmented by sending a message with a delay.
But up until now, there was no way to indicate to the StateFun runtime that a particular delayed message is not necessary anymore (a customer had completed their onboarding flow).
With StateFun 3.1, it is now possible to cancel a delayed message.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="n">context</span><span class="o">.</span><span class="n">send_after</span><span class="p">(</span><span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">3</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"> <span class="n">message_builder</span><span class="p">(</span><span class="n">target_typename</span><span class="o">=</span><span class="s2">&#34;fns/onboarding&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">target_id</span><span class="o">=</span><span class="s2">&#34;user-1234&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="n">str_value</span><span class="o">=</span><span class="s2">&#34;send a reminder email&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"> <span class="n">cancellation_token</span><span class="o">=</span><span class="s2">&#34;flow-1234&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="o">...</span>
</span></span></code></pre></div><p>To cancel the message at a later time, simply call</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">context</span><span class="o">.</span><span class="n">cancel_delayed_message</span><span class="p">(</span><span class="s2">&#34;flow-1234&#34;</span><span class="p">)</span>
</span></span></code></pre></div><p>Please note that a message cancellation occurs on a best-effort basis, as the message might have already been delivered or enqueued for immediate delivery on a remote worker’s mailbox.</p>
<h3 id="new-way-to-specify-components">
New way to specify components
<a class="anchor" href="#new-way-to-specify-components">#</a>
</h3>
<p>StateFun applications consist of multiple configuration components, including remote function endpoints, along with ingress and egress definitions, defined in a YAML format.
We&rsquo;ve added a new structure that treats each StateFun component as a standalone YAML document in this release.
Thus, a <code>module.yaml</code> file becomes simply a collection of components.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">io.statefun.endpoints.v2/http</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">functions</span><span class="p">:</span><span class="w"> </span><span class="l">com.example/*</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">urlPathTemplate</span><span class="p">:</span><span class="w"> </span><span class="l">https://bar.foo.com/{function.name}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">io.statefun.kafka.v1/ingress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">com.example/my-ingress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">address</span><span class="p">:</span><span class="w"> </span><span class="l">kafka-broker:9092</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">consumerGroupId</span><span class="p">:</span><span class="w"> </span><span class="l">my-consumer-group</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">topics</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">topic</span><span class="p">:</span><span class="w"> </span><span class="l">message-topic</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">valueType</span><span class="p">:</span><span class="w"> </span><span class="l">io.statefun.types/string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">targets</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">com.example/greeter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">io.statefun.kafka.v1/egress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">com.example/my-egress</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">address</span><span class="p">:</span><span class="w"> </span><span class="l">kafka-broker:9092</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">deliverySemantic</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">exactly-once</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">transactionTimeout</span><span class="p">:</span><span class="w"> </span><span class="l">15min</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nn">---</span><span class="w">
</span></span></span></code></pre></div><p>While this might seem like a minor cosmetic improvement, this change opens the door to more flexible configuration management options in future releases - such as managing each component as a custom K8s resource definition or even behind a REST API. StateFun still supports the legacy module format in version 3.0 for backward compatibility, but users are encouraged to upgrade.
The community is providing an <a href="https://github.com/sjwiesman/statefun-module-upgrade">automated migration tool</a> to ease the transition.</p>
<h3 id="pluggable-transport-for-remote-function-invocations">
Pluggable transport for remote function invocations
<a class="anchor" href="#pluggable-transport-for-remote-function-invocations">#</a>
</h3>
<p>It is possible to plugin a custom mechanism that invokes a remote stateful function starting with this release.
Users who wish to use a customized transport need to register it as an extension and later reference it straight from the endpoint component definition.</p>
<p>For example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">io.statefun.endpoints.v2/http</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">functions</span><span class="p">:</span><span class="w"> </span><span class="l">com.foo.bar/*</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">urlPathTemplate</span><span class="p">:</span><span class="w"> </span><span class="l">https://{function.name}/</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">maxNumBatchRequests</span><span class="p">:</span><span class="w"> </span><span class="m">10000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">transport</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">com.foo.bar/pubsub</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">some_property1</span><span class="p">:</span><span class="w"> </span><span class="l">some_value1</span><span class="w">
</span></span></span></code></pre></div><p>For a complete example of a custom transport you can start exploring <a href="https://github.com/apache/flink-statefun/blob/release-3.1.0/statefun-flink/statefun-flink-core/src/main/java/org/apache/flink/statefun/flink/core/nettyclient/NettyTransportModule.java">here</a>.
Along with a reference usage over <a href="https://github.com/apache/flink-statefun/blob/release-3.1.0/statefun-e2e-tests/statefun-smoke-e2e-java/src/test/resources/remote-module/module.yaml#L21-L22">here</a>.</p>
<h3 id="asynchronous-non-blocking-remote-function-invocation-beta">
Asynchronous, non blocking remote function invocation (beta)
<a class="anchor" href="#asynchronous-non-blocking-remote-function-invocation-beta">#</a>
</h3>
<p>For this release we’ve included a new transport implementation (opt in for this release) that is implemented on top of the asynchronous Netty framework.
This transport enables much higher resource utilization, higher throughput, and lower remote function invocation latency.</p>
<p>To enable this new transport, set the transport type to be <code>io.statefun.transports.v1/async</code>
Like in the following example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">io.statefun.endpoints.v2/http</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">functions</span><span class="p">:</span><span class="w"> </span><span class="l">fns/*</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">urlPathTemplate</span><span class="p">:</span><span class="w"> </span><span class="l">https://api-gateway.foo.bar/{function.name}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">maxNumBatchRequests</span><span class="p">:</span><span class="w"> </span><span class="m">10000</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">transport</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">io.statefun.transports.v1/async</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">call</span><span class="p">:</span><span class="w"> </span><span class="l">2m</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">connect</span><span class="p">:</span><span class="w"> </span><span class="l">20s</span><span class="w">
</span></span></span></code></pre></div><p>Take it for a spin!</p>
<h3 id="a-brand-new-golang-sdk">
A brand new GoLang SDK
<a class="anchor" href="#a-brand-new-golang-sdk">#</a>
</h3>
<p>Stateful Functions provides a unified model for building stateful applications across various programming languages and deployment environments.
The community is thrilled to release an official GoLang SDK as part of the 3.1.0 release.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">&#34;fmt&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="s">&#34;github.com/apache/flink-statefun/statefun-sdk-go/v3/pkg/statefun&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="s">&#34;net/http&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Greeter</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">SeenCount</span> <span class="nx">statefun</span><span class="p">.</span><span class="nx">ValueSpec</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">g</span> <span class="o">*</span><span class="nx">Greeter</span><span class="p">)</span> <span class="nf">Invoke</span><span class="p">(</span><span class="nx">ctx</span> <span class="nx">statefun</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span> <span class="nx">message</span> <span class="nx">statefun</span><span class="p">.</span><span class="nx">Message</span><span class="p">)</span> <span class="kt">error</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">storage</span> <span class="o">:=</span> <span class="nx">ctx</span><span class="p">.</span><span class="nf">Storage</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1">// Read the current value of the state
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// or zero value if no value is set
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">count</span> <span class="kt">int32</span>
</span></span><span class="line"><span class="cl"> <span class="nx">storage</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="nx">g</span><span class="p">.</span><span class="nx">SeenCount</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">count</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">count</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="c1">// Update the state which will
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="c1">// be made persistent by the runtime
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">storage</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="nx">g</span><span class="p">.</span><span class="nx">SeenCount</span><span class="p">,</span> <span class="nx">count</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">name</span> <span class="o">:=</span> <span class="nx">message</span><span class="p">.</span><span class="nf">AsString</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="nx">greeting</span> <span class="o">:=</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprintf</span><span class="p">(</span><span class="s">&#34;Hello there %s at the %d-th time!\n&#34;</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">count</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">ctx</span><span class="p">.</span><span class="nf">Send</span><span class="p">(</span><span class="nx">statefun</span><span class="p">.</span><span class="nx">MessageBuilder</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Target</span><span class="p">:</span> <span class="o">*</span><span class="nx">ctx</span><span class="p">.</span><span class="nf">Caller</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Value</span><span class="p">:</span> <span class="nx">greeting</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">greeter</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">Greeter</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">SeenCount</span><span class="p">:</span> <span class="nx">statefun</span><span class="p">.</span><span class="nx">ValueSpec</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;seen_count&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">ValueType</span><span class="p">:</span> <span class="nx">statefun</span><span class="p">.</span><span class="nx">Int32Type</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">builder</span> <span class="o">:=</span> <span class="nx">statefun</span><span class="p">.</span><span class="nf">StatefulFunctionsBuilder</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="nx">_</span> <span class="p">=</span> <span class="nx">builder</span><span class="p">.</span><span class="nf">WithSpec</span><span class="p">(</span><span class="nx">statefun</span><span class="p">.</span><span class="nx">StatefulFunctionSpec</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">FunctionType</span><span class="p">:</span> <span class="nx">statefun</span><span class="p">.</span><span class="nf">TypeNameFrom</span><span class="p">(</span><span class="s">&#34;com.example.fns/greeter&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"> <span class="nx">States</span><span class="p">:</span> <span class="p">[]</span><span class="nx">statefun</span><span class="p">.</span><span class="nx">ValueSpec</span><span class="p">{</span><span class="nx">greeter</span><span class="p">.</span><span class="nx">SeenCount</span><span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Function</span><span class="p">:</span> <span class="nx">greeter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="nx">http</span><span class="p">.</span><span class="nf">Handle</span><span class="p">(</span><span class="s">&#34;/statefun&#34;</span><span class="p">,</span> <span class="nx">builder</span><span class="p">.</span><span class="nf">AsHandler</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"> <span class="nx">_</span> <span class="p">=</span> <span class="nx">http</span><span class="p">.</span><span class="nf">ListenAndServe</span><span class="p">(</span><span class="s">&#34;:8000&#34;</span><span class="p">,</span> <span class="kc">nil</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>As with the Python and Java SDKs, the Go SDK includes:</p>
<ul>
<li>An address scoped storage acting as a key-value store for a particular address.</li>
<li>A unified cross-language way to send, receive and store values across languages.</li>
<li>Dynamic <code>ValueSpec</code> to describe the state name, type, and possibly expiration configuration at runtime.</li>
</ul>
<p>You can get started by adding the SDK to your <code>go.mod</code> file.</p>
<p><code>require github.com/apache/flink-statefun/statefun-sdk-go/v3 v3.1.0</code></p>
<p>For a detailed SDK tutorial, we would like to encourage you to visit:</p>
<ul>
<li><a href="https://github.com/apache/flink-statefun-playground/tree/release-3.1/go/showcase">GoLang SDK Showcase</a></li>
<li><a href="https://github.com/apache/flink-statefun-playground/tree/release-3.1/go/greeter">GoLang Greeter</a></li>
<li><a href="//nightlies.apache.org/flink/flink-statefun-docs-release-3.1/docs/sdk/golang/">GoLang SDK Documentation</a></li>
</ul>
<h2 id="release-notes">
Release Notes
<a class="anchor" href="#release-notes">#</a>
</h2>
<h2 id="release-notes-1">
Release Notes
<a class="anchor" href="#release-notes-1">#</a>
</h2>
<p>Please review the <a href="https://issues.apache.org/jira/secure/ReleaseNote.jspa?version=12350038&amp;projectId=12315522">release notes</a>
for a detailed list of changes and new features if you plan to upgrade your setup to Stateful Functions 3.1.0.</p>
<h2 id="list-of-contributors">
List of Contributors
<a class="anchor" href="#list-of-contributors">#</a>
</h2>
<p>Evans Ye, George Birbilis, Igal Shilman, Konstantin Knauf, Seth Wiesman, Siddique Ahmad, Tzu-Li (Gordon) Tai, ariskk, austin ce</p>
<p>If you’d like to get involved, we’re always <a href="https://github.com/apache/flink-statefun#contributing">looking for new contributors</a>.</p>
</p>
</article>
<div class="edit-this-page">
<p>
<a href="https://cwiki.apache.org/confluence/display/FLINK/Flink+Translation+Specifications">Want to contribute translation?</a>
</p>
<p>
<a href="//github.com/apache/flink-web/edit/asf-site/docs/content/posts/2021-08-31-release-statefun-3.1.0.md">
Edit This Page<i class="fa fa-edit fa-fw"></i>
</a>
</p>
</div>
</section>
<aside class="book-toc">
<nav id="TableOfContents"><h3>On This Page <a href="javascript:void(0)" class="toc" onclick="collapseToc()"><i class="fa fa-times" aria-hidden="true"></i></a></h3>
<ul>
<li>
<ul>
<li><a href="#new-features">New Features</a>
<ul>
<li><a href="#delayed-message-cancellation">Delayed Message Cancellation</a></li>
<li><a href="#new-way-to-specify-components">New way to specify components</a></li>
<li><a href="#pluggable-transport-for-remote-function-invocations">Pluggable transport for remote function invocations</a></li>
<li><a href="#asynchronous-non-blocking-remote-function-invocation-beta">Asynchronous, non blocking remote function invocation (beta)</a></li>
<li><a href="#a-brand-new-golang-sdk">A brand new GoLang SDK</a></li>
</ul>
</li>
<li><a href="#release-notes">Release Notes</a></li>
<li><a href="#release-notes-1">Release Notes</a></li>
<li><a href="#list-of-contributors">List of Contributors</a></li>
</ul>
</li>
</ul>
</nav>
</aside>
<aside class="expand-toc hidden">
<a class="toc" onclick="expandToc()" href="javascript:void(0)">
<i class="fa fa-bars" aria-hidden="true"></i>
</a>
</aside>
</main>
<footer>
<div class="separator"></div>
<div class="panels">
<div class="wrapper">
<div class="panel">
<ul>
<li>
<a href="https://flink-packages.org/">flink-packages.org</a>
</li>
<li>
<a href="https://www.apache.org/">Apache Software Foundation</a>
</li>
<li>
<a href="https://www.apache.org/licenses/">License</a>
</li>
<li>
<a href="/zh/">
<i class="fa fa-globe" aria-hidden="true"></i>&nbsp;中文版
</a>
</li>
</ul>
</div>
<div class="panel">
<ul>
<li>
<a href="/what-is-flink/security">Security</a-->
</li>
<li>
<a href="https://www.apache.org/foundation/sponsorship.html">Donate</a>
</li>
<li>
<a href="https://www.apache.org/foundation/thanks.html">Thanks</a>
</li>
</ul>
</div>
<div class="panel icons">
<div>
<a href="/posts">
<div class="icon flink-blog-icon"></div>
<span>Flink blog</span>
</a>
</div>
<div>
<a href="https://github.com/apache/flink">
<div class="icon flink-github-icon"></div>
<span>Github</span>
</a>
</div>
<div>
<a href="https://twitter.com/apacheflink">
<div class="icon flink-twitter-icon"></div>
<span>Twitter</span>
</a>
</div>
</div>
</div>
</div>
<hr/>
<div class="container disclaimer">
<p>The contents of this website are © 2024 Apache Software Foundation under the terms of the Apache License v2. Apache Flink, Flink, and the Flink logo are either registered trademarks or trademarks of The Apache Software Foundation in the United States and other countries.</p>
</div>
</footer>
</body>
</html>