<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Apache OpenDAL™ Blog</title>
        <link>https://opendal.apache.org/blog/</link>
        <description>Apache OpenDAL™ Blog</description>
        <lastBuildDate>Mon, 15 Sep 2025 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[reqsign is now Apache OpenDAL Reqsign]]></title>
            <link>https://opendal.apache.org/blog/2025/09/15/apache-opendal-reqsign/</link>
            <guid>https://opendal.apache.org/blog/2025/09/15/apache-opendal-reqsign/</guid>
            <pubDate>Mon, 15 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[I’m happy to announce that my personal project has been donated to the ASF and accepted by the Apache OpenDAL PMC as a subproject: Apache OpenDAL Reqsign. This means Reqsign will now be governed by the Apache OpenDAL PMC under the Apache Way.]]></description>
            <content:encoded><![CDATA[<p>I’m happy to announce that my personal project has been donated to the ASF and accepted by the Apache OpenDAL PMC as a subproject: <a href="https://github.com/apache/opendal-reqsign" target="_blank" rel="noopener noreferrer" class="">Apache OpenDAL Reqsign</a>. This means Reqsign will now be governed by the Apache OpenDAL PMC under <a href="https://www.apache.org/theapacheway/" target="_blank" rel="noopener noreferrer" class="">the Apache Way</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="what-is-reqsign">What is Reqsign?<a href="https://opendal.apache.org/blog/2025/09/15/apache-opendal-reqsign/#what-is-reqsign" class="hash-link" aria-label="Direct link to What is Reqsign?" title="Direct link to What is Reqsign?" translate="no">​</a></h2>
<p>Reqsign stands for <code>Request Signing</code>. Its goal is to make signing API requests simple. Many APIs look straightforward, but they quickly become complicated once hidden behind complex abstractions.</p>
<p>One major challenge is authentication. For example, AWS V4 requires users to build a signature from the request and sign it using HMAC with a secret key. Another challenge is credential loading. Cloud providers like AWS, Azure, and GCP support various types of credentials and loading methods to balance security and ease of use.</p>
<p>All these features together make simple APIs feel complex. To send a single <code>GetObject</code> call, you often need to rely on many AWS crates and go through deep abstraction layers.</p>
<p>Reqsign's goal is to bring simplicity back: build, sign, send.</p>
<p>In general, Reqsign provides three main parts for different services:</p>
<ul>
<li class=""><code>ProvideCredential</code>: Lets users provide credentials in different ways such as environment variables, profiles, <code>IMDS</code>, <code>OIDC</code>, and more. Reqsign also provides a default chain for every service so it works out of the box without extra configuration.</li>
<li class=""><code>SignRequest</code>: Implements the signing logic so that requests are correctly signed with the given provider credentials.</li>
<li class=""><code>Context</code>: Offers a pluggable context mechanism that supports HTTP send, command execution, and environment access. This allows users to configure the runtime context as they wish and makes Reqsign available in WASM.</li>
</ul>
<p>For example:</p>
<div class="language-rust codeBlockContainer_RtmP theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_Pm3P"><pre tabindex="0" class="prism-code language-rust codeBlock_JK9j thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_ODIi"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">anyhow</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">reqsign</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token plain">aws</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[tokio::main]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Create a default signer for S3 in us-east-1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// This will automatically:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// - Load credentials from environment variables, config files, or IAM roles</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// - Set up the default HTTP client and file reader</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> signer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">aws</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">default_signer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"s3"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"us-east-1"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Build your request</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> req </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">http</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Request</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">method</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"GET"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">uri</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"https://s3.amazonaws.com/testbucket"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">into_parts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Sign the request</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    signer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sign</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> req</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">None</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Send the request with your preferred HTTP client</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Request has been signed!"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>Currently, Reqsign supports Aliyun OSS, AWS V4, Azure Storage, Google, Huawei Cloud OBS, Oracle, and Tencent COS. The community is working on adding more services so that users do not need to reimplement them.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="what-has-changed-and-what-has-not">What has changed and what has not?<a href="https://opendal.apache.org/blog/2025/09/15/apache-opendal-reqsign/#what-has-changed-and-what-has-not" class="hash-link" aria-label="Direct link to What has changed and what has not?" title="Direct link to What has changed and what has not?" translate="no">​</a></h2>
<p>After this donation, Reqsign has become a subproject of Apache OpenDAL. The Apache OpenDAL PMC will govern the project under the Apache Way. The repository has been transferred from <code>Xuanwo/reqsign</code> to <code>apache/opendal-reqsign</code>. All Reqsign committers are now OpenDAL committers.</p>
<p>Reqsign is licensed under Apache 2.0. Joining the ASF strengthens this license and makes it permanent. Everyone can now use Reqsign in a safe and trusted way. The community will dedicate more effort to fixing bugs and adding new features to help Reqsign grow into a mature project.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="whats-next">What’s next?<a href="https://opendal.apache.org/blog/2025/09/15/apache-opendal-reqsign/#whats-next" class="hash-link" aria-label="Direct link to What’s next?" title="Direct link to What’s next?" translate="no">​</a></h2>
<p>The OpenDAL community is working to make Reqsign ready as a mature ASF project and integrate it with Reqsign v1.0. We also plan to move some existing service implementations into Reqsign for better maintainability.</p>
<p>Welcome to join us!</p>]]></content:encoded>
            <category>announcement</category>
        </item>
        <item>
            <title><![CDATA[Apache OpenDAL 2025 Roadmap: Perfecting Production Adoption]]></title>
            <link>https://opendal.apache.org/blog/2025/03/01/2025-roadmap/</link>
            <guid>https://opendal.apache.org/blog/2025/03/01/2025-roadmap/</guid>
            <pubDate>Sat, 01 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Hi everyone, long time no see. Although we have been actively developing OpenDAL and consistently releasing updates, we haven’t provided a clear overview of where OpenDAL is heading. This post aims to address that. Here, we will discuss OpenDAL's current position and the future directions we are moving toward.]]></description>
            <content:encoded><![CDATA[<p>Hi everyone, long time no see. Although we have been actively developing OpenDAL and consistently releasing updates, we haven’t provided a clear overview of where OpenDAL is heading. This post aims to address that. Here, we will discuss OpenDAL's current position and the future directions we are moving toward.</p>
<p>I hope this post serves as a guide for our development, encourages more people to contribute, and ultimately helps achieve the vision of OpenDAL.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="whats-opendal">What's OpenDAL?<a href="https://opendal.apache.org/blog/2025/03/01/2025-roadmap/#whats-opendal" class="hash-link" aria-label="Direct link to What's OpenDAL?" title="Direct link to What's OpenDAL?" translate="no">​</a></h2>
<p>Apache OpenDAL (<code>/ˈoʊ.pən.dæl/</code>, pronounced "OH-puhn-dal") is an Open Data Access Layer that enables seamless interaction with diverse storage services. Our VISION is <a href="https://opendal.apache.org/vision" target="_blank" rel="noopener noreferrer" class=""><strong>One Layer, All Storage</strong></a>, and our core principles are Open Community, Solid Foundation, Fast Access, Object Storage First, and Extensible Architecture.</p>
<p>We are building:</p>
<ul>
<li class=""><a href="https://crates.io/crates/opendal" target="_blank" rel="noopener noreferrer" class="">A core library built in Rust</a> that supports all services at zero cost and offers unified retry, concurrency, logging, tracing, metrics, timeout and more layers.</li>
<li class="">Language bindings for <a href="https://pypi.org/project/opendal/" target="_blank" rel="noopener noreferrer" class="">Python</a>, <a href="https://central.sonatype.com/artifact/org.apache.opendal/opendal" target="_blank" rel="noopener noreferrer" class="">Java</a>, <a href="https://www.npmjs.com/package/opendal" target="_blank" rel="noopener noreferrer" class="">Node.js</a>, C/C++, and more.</li>
<li class="">Integrations with various frameworks, including <a href="https://crates.io/crates/parquet-opendal" target="_blank" rel="noopener noreferrer" class="">Parquet</a>, <a href="https://crates.io/crates/fuse3_opendal" target="_blank" rel="noopener noreferrer" class="">FUSE</a>, <a href="https://github.com/messense/dav-server-rs" target="_blank" rel="noopener noreferrer" class="">DAV server</a>, and others.</li>
<li class="">Binaries for different use cases, such as <a href="https://crates.io/crates/oli" target="_blank" rel="noopener noreferrer" class="">CLI</a> and <a href="https://crates.io/crates/ofs" target="_blank" rel="noopener noreferrer" class="">FUSE</a>.</li>
</ul>
<p>In short, through OpenDAL, users can access ALL storage services within ONE layer.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="wheres-opendal">Where's OpenDAL?<a href="https://opendal.apache.org/blog/2025/03/01/2025-roadmap/#wheres-opendal" class="hash-link" aria-label="Direct link to Where's OpenDAL?" title="Direct link to Where's OpenDAL?" translate="no">​</a></h2>
<p>OpenDAL's rust core has already released 143 versions, has <a href="https://crates.io/crates/opendal/reverse_dependencies" target="_blank" rel="noopener noreferrer" class="">67 reverse dependencies</a> listed on <a href="http://crates.io/" target="_blank" rel="noopener noreferrer" class="">crates.io</a>, and is used by <a href="https://github.com/apache/opendal/network/dependents" target="_blank" rel="noopener noreferrer" class="">612 projects</a> as recorded on GitHub.</p>
<p>OpenDAL's production users include databases such as <a href="https://github.com/databendlabs/databend" target="_blank" rel="noopener noreferrer" class="">Databend</a>, <a href="https://github.com/GreptimeTeam/greptimedb" target="_blank" rel="noopener noreferrer" class="">GreptimeDB</a>, and <a href="https://github.com/risingwavelabs/risingwave" target="_blank" rel="noopener noreferrer" class="">RisingWave</a>, as well as tools like <a href="https://loco.rs/" target="_blank" rel="noopener noreferrer" class="">Loco</a>, <a href="https://github.com/mozilla/sccache" target="_blank" rel="noopener noreferrer" class="">sccache</a>, and <a href="https://vector.dev/" target="_blank" rel="noopener noreferrer" class="">Vector</a>.</p>
<p><img decoding="async" loading="lazy" src="https://opendal.apache.org/assets/images/opendal-rust-downloads-8f5b499b4cd72f80bd63ad4f34500f78.png" width="1928" height="1300" class="img_EjcX"></p>
<p>Apart from OpenDAL's Rust core, its various language bindings have also seen significant growth over the past year. Take python binding as an example. <a href="https://github.com/langgenius/dify/" target="_blank" rel="noopener noreferrer" class="">Dify</a>, an LLM app development platform, is using OpenDAL to access different storage services.</p>
<p><img decoding="async" loading="lazy" src="https://opendal.apache.org/assets/images/opendal-python-downloads-c5d552b37aa69309d8b3c032b686dc98.png" width="2502" height="796" class="img_EjcX"></p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="whats-next-for-opendal">What's next for OpenDAL?<a href="https://opendal.apache.org/blog/2025/03/01/2025-roadmap/#whats-next-for-opendal" class="hash-link" aria-label="Direct link to What's next for OpenDAL?" title="Direct link to What's next for OpenDAL?" translate="no">​</a></h2>
<p>The following is the famous technology adoption lifecycle curve. If I were to indicate the position of OpenDAL, I would say it is at the end of the Innovators stage and moving toward the Early Adopters stage.</p>
<p><img decoding="async" loading="lazy" src="https://opendal.apache.org/assets/images/adoption-curve-d76b6c9b5a8c14661c9800fc4b4ec239.png" width="1200" height="720" class="img_EjcX">
(picture from TechTarget <a href="https://www.techtarget.com/searchcio/definition/technology-adoption-lifecycle" target="_blank" rel="noopener noreferrer" class="">technology adoption lifecycle</a>)</p>
<p>Innovators are adopting OpenDAL. Projects like Databend, RisingWave, GreptimeDB, and sccache have been using OpenDAL in production for years. However, early adopters are still hesitant to use OpenDAL—and they have valid reasons.</p>
<p>For examples:</p>
<ul>
<li class="">OpenDAL hasn't reached version 1.0 yet and still introduces breaking changes from time to time, sometimes even requiring code modifications for an OpenDAL upgrade. This also creates a burden for libraries that depend on OpenDAL, as every breaking change affects them as well.</li>
<li class="">OpenDAL lacks comprehensive documentation, particularly for its bindings in Python and Java. Users need to invest significant effort and love to integrate OpenDAL bindings into their projects.</li>
<li class="">OpenDAL lacks some important features, such as checksum support, caching, metrics of underlying http requests and initialization from a URI.</li>
</ul>
<p>I believe we should perfect production adoption in 2025 to get OpenDAL ready for early adopters. Only in this way can we implement our vision: <strong>One Layer, All Storage.</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="what-to-do-in-2025">What to do in 2025?<a href="https://opendal.apache.org/blog/2025/03/01/2025-roadmap/#what-to-do-in-2025" class="hash-link" aria-label="Direct link to What to do in 2025?" title="Direct link to What to do in 2025?" translate="no">​</a></h2>
<p>Our plans for 2025 include the following:</p>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="features-needed-in-production">Features Needed in Production<a href="https://opendal.apache.org/blog/2025/03/01/2025-roadmap/#features-needed-in-production" class="hash-link" aria-label="Direct link to Features Needed in Production" title="Direct link to Features Needed in Production" translate="no">​</a></h3>
<p>In 2025, we plan to implement the following features that are importmant for production adoption:</p>
<ul>
<li class=""><a href="https://github.com/apache/opendal/issues/5480" target="_blank" rel="noopener noreferrer" class="">Context</a>: Introduce context in OpenDAL so that services and layers can share the same context. This enables users to gain deeper insights into OpenDAL's internal operations by incorporating metrics, logging, and tracing into the underlying HTTP client we use.</li>
<li class=""><a href="https://github.com/apache/opendal/issues/2611" target="_blank" rel="noopener noreferrer" class="">Versioning</a>: Introduce full file versioning support in OpenDAL, enabling users to read, write, delete, list, and restore versioned files. This functionality will allow users to recover mistakenly deleted files and facilitate disaster recovery.</li>
<li class=""><a href="https://github.com/apache/opendal/issues/5549" target="_blank" rel="noopener noreferrer" class="">Checksum</a>: Introduce end-to-end checksum support in OpenDAL, enabling users to perform checksums during reading and writing without worrying about bit flips in memory or over the network.</li>
<li class=""><a href="https://github.com/apache/opendal/issues/5678" target="_blank" rel="noopener noreferrer" class="">Caching</a>: Provide high-quality built-in cache support in OpenDAL while ensuring users have the flexibility to implement their own caching logic.</li>
<li class=""><a href="https://github.com/apache/opendal/issues/3022" target="_blank" rel="noopener noreferrer" class="">Initialization From URI</a>: Allow users to initialize OpenDAL from a URI string, making it easier to configure and use OpenDAL in various environments.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="improvements-needed-for-production">Improvements Needed for Production<a href="https://opendal.apache.org/blog/2025/03/01/2025-roadmap/#improvements-needed-for-production" class="hash-link" aria-label="Direct link to Improvements Needed for Production" title="Direct link to Improvements Needed for Production" translate="no">​</a></h3>
<p>In 2025, we plan to improve the following aspects of OpenDAL to ensure users can confidently use it in production.</p>
<ul>
<li class="">Documentation: Improve the documentation for OpenDAL, particularly for bindings like Python, Node.js, and Java. The first step is to generate well-structured documentation for the configuration values of each service.</li>
<li class="">Communitation: Bring Back Our Community Meetings. OpenDAL used to hold regular tri-weekly meetings, but we have been unable to maintain them in the last year. We now plan to revive these meetings and encourage more face-to-face discussions in the coming years.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="conclusion">Conclusion<a href="https://opendal.apache.org/blog/2025/03/01/2025-roadmap/#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>2025 marks the third year of the OpenDAL community. A huge thanks to all OpenDAL contributors and users for helping us reach this milestone. There's still a long way to go to achieve our vision, and we invite you all to join us on this incredible journey!</p>
<p><a href="https://github.com/apache/opendal/discussions/5679" target="_blank" rel="noopener noreferrer" class="">Discuss about this post here</a></p>]]></content:encoded>
            <category>announcement</category>
        </item>
        <item>
            <title><![CDATA[Apache OpenDAL™ Beijing Meetup 1st]]></title>
            <link>https://opendal.apache.org/blog/2024/09/09/apache-opendal-meetup-beijing-1st/</link>
            <guid>https://opendal.apache.org/blog/2024/09/09/apache-opendal-meetup-beijing-1st/</guid>
            <pubDate>Mon, 09 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Hello, everyone!]]></description>
            <content:encoded><![CDATA[<p>Hello, everyone!</p>
<p>On behalf of the OpenDAL community, I'm pleased to announce that the first Apache OpenDAL™ Beijing Meetup will be held on September 14th.</p>
<p>You are welcome to register for this event at: <a href="https://docs.qq.com/form/page/DYnpJWFFsSWVFeGRj" target="_blank" rel="noopener noreferrer" class="">https://docs.qq.com/form/page/DYnpJWFFsSWVFeGRj</a></p>
<p>The event will take place at <a href="https://maps.app.goo.gl/4Tr7JCJ5HdCoVGdeA" target="_blank" rel="noopener noreferrer" class="">北京市朝阳区北辰西路 8 号北辰世纪中心A座12层1215房间（国家会议中心西面的写字楼）</a> on the afternoon of September 14th.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="agenda">Agenda<a href="https://opendal.apache.org/blog/2024/09/09/apache-opendal-meetup-beijing-1st/#agenda" class="hash-link" aria-label="Direct link to Agenda" title="Direct link to Agenda" translate="no">​</a></h2>
<ul>
<li class="">12:00 - 13:00: Lunch / Networking (food provided)</li>
<li class="">13:00 - 14:00: Welcome / Introductions</li>
<li class="">14:00 - 15:00: Talks</li>
<li class="">15:00 - 15:30: Coffee / Email Break</li>
<li class="">15:30 - 16:30: Breakouts / Discussions</li>
<li class="">16:30 - 17:00: Close / Conclusion</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="welcome">Welcome<a href="https://opendal.apache.org/blog/2024/09/09/apache-opendal-meetup-beijing-1st/#welcome" class="hash-link" aria-label="Direct link to Welcome" title="Direct link to Welcome" translate="no">​</a></h2>
<p>Brief introductory remarks, thank to the sponsor, outline of the day, participant introductions (name, github handle, optional affiliation, optional reason you came to the meetup)</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="talks">Talks<a href="https://opendal.apache.org/blog/2024/09/09/apache-opendal-meetup-beijing-1st/#talks" class="hash-link" aria-label="Direct link to Talks" title="Direct link to Talks" translate="no">​</a></h2>
<p>Five 10-15 minute talks about opendal.</p>
<ul>
<li class=""><a href="https://github.com/tisonkun/" target="_blank" rel="noopener noreferrer" class="">@tisonkun</a> about OpenDAL Community Growth</li>
<li class=""><a href="https://github.com/WenyXu/" target="_blank" rel="noopener noreferrer" class="">@WenyXu</a> for using OpenDAL in <a href="https://github.com/GreptimeTeam/greptimedb" target="_blank" rel="noopener noreferrer" class="">GreptimeDB</a></li>
<li class=""><a href="https://github.com/wcy-fdu/" target="_blank" rel="noopener noreferrer" class="">@wcy-fdu</a> for using OpenDAL in <a href="https://github.com/risingwavelabs/risingwave" target="_blank" rel="noopener noreferrer" class="">RisingWave</a></li>
<li class=""><a href="https://github.com/wcy-fdu/" target="_blank" rel="noopener noreferrer" class="">@drmingdrmer</a> for using OpenDAL in <a href="https://github.com/datafuselabs/openraft" target="_blank" rel="noopener noreferrer" class="">OpenRaft</a></li>
<li class=""><a href="https://github.com/Xuanwo/" target="_blank" rel="noopener noreferrer" class="">@Xuanwo</a> about OpenDAL Core 1.0</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="breakouts--discussions">Breakouts / Discussions<a href="https://opendal.apache.org/blog/2024/09/09/apache-opendal-meetup-beijing-1st/#breakouts--discussions" class="hash-link" aria-label="Direct link to Breakouts / Discussions" title="Direct link to Breakouts / Discussions" translate="no">​</a></h2>
<p>The idea is that we will break into small groups for 3 x 20 minute sessions. I will ring a gong or something similar every 20 minutes and you should find a new group to discuss.</p>
<p>Potential seed topics (but obviously feel free to discuss anything):</p>
<ul>
<li class="">How do we make it easier for people to build systems on OpenDAL? What are the current barriers to community growth as you see them?</li>
<li class="">How do we make it easier for people to contribute back to OpenDAL? What are the current barriers to contribution</li>
<li class="">What features would you like to see / not see</li>
</ul>
<p>Ideally, in each session, one or more people would volunteer to write up any insights they got from the discussions, and post them to the overall ticket.</p>
<hr>
<p>Looking forward to meet you in this meetup!</p>]]></content:encoded>
            <category>announcement</category>
        </item>
        <item>
            <title><![CDATA[Apache OpenDAL™ participates in Open Source Promotion Plan 2024]]></title>
            <link>https://opendal.apache.org/blog/apache-opendal-participates-in-ospp-2024/</link>
            <guid>https://opendal.apache.org/blog/apache-opendal-participates-in-ospp-2024/</guid>
            <pubDate>Tue, 30 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Hello, everyone!]]></description>
            <content:encoded><![CDATA[<p>Hello, everyone!</p>
<p>We're writing this blog post to announce that the Apache OpenDAL™ Project will be participating in <a href="https://summer-ospp.ac.cn/" target="_blank" rel="noopener noreferrer" class="">Open Source Promotion Plan (OSPP) 2024</a>. If you're not eligible or interested in participating in OSPP, then most of this post likely isn't relevant to you; if you are, this should contain some useful information and links.</p>
<p>Open Source Promotion Plan is a summer program organized by the Institute of Software Chinese Academy of Sciences and long-term supported by the Open Source Software Supply Chain Promotion Plan. It aims to encourage college students to actively participate in the maintenance and development of open source software, promote the vigorous development of open source software communities, and build the open source software supply chain together.</p>
<p>The OSPP applicants now have several weeks to send project proposals to organizations that appeal to them. If their project proposal is accepted, they will embark on a 12-week journey during which they will try to complete their proposed project under the guidance of an assigned mentor.</p>
<p>We have prepared <a href="https://github.com/apache/opendal/issues/4554" target="_blank" rel="noopener noreferrer" class="">a list of project ideas</a> that can serve as inspiration for potential OSPP contributors that would like to send a project proposal to the OpenDAL project. You can try to find mentors on the <a href="mailto:dev@opendal.apache.org" target="_blank" rel="noopener noreferrer" class="">maillist</a> or <a href="https://discord.gg/XQy8yGR2dg" target="_blank" rel="noopener noreferrer" class="">Discord</a>. We have also prepared <a href="https://opendal.apache.org/community/events/ospp-proposal-guide" target="_blank" rel="noopener noreferrer" class="">a proposal guide</a> that should help you with preparing your project proposals.</p>
<p>You can start discussing the project ideas with OpenDAL Project maintainers immediately. The project proposal application period starts on April 30, 2024, and ends on June 4, 2024. Take note of that deadline, as there will be no extensions!</p>
<p>If you are interested in contributing to the OpenDAL Project, we encourage you to check out our project idea list and send us a OSPP project proposal! Of course, you are also free to discuss these projects and/or try to move them forward even if you do not intend to (or cannot) participate in OSPP. We welcome all contributors to OpenDAL, as there is always enough work to do.</p>
<p>We are excited about this event. Hoping you all feel the same way!</p>
<blockquote>
<p>This announcement is inspired a lot by the <a href="https://blog.rust-lang.org/2024/02/21/Rust-participates-in-GSoC-2024.html" target="_blank" rel="noopener noreferrer" class="">Rust participates in Google Summer of Code 2024</a>.</p>
</blockquote>]]></content:encoded>
            <category>announcement</category>
        </item>
        <item>
            <title><![CDATA[Apache OpenDAL™ participates in Google Summer of Code 2024]]></title>
            <link>https://opendal.apache.org/blog/apache-opendal-participates-in-gsoc-2024/</link>
            <guid>https://opendal.apache.org/blog/apache-opendal-participates-in-gsoc-2024/</guid>
            <pubDate>Wed, 28 Feb 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Hello, everyone!]]></description>
            <content:encoded><![CDATA[<p>Hello, everyone!</p>
<p>We're writing this blog post to announce that the Apache OpenDAL™ Project will be participating in <a href="https://summerofcode.withgoogle.com/" target="_blank" rel="noopener noreferrer" class="">Google Summer of Code (GSoC) 2024</a>. If you're not eligible or interested in participating in GSoC, then most of this post likely isn't relevant to you; if you are, this should contain some useful information and links.</p>
<p>Google Summer of Code (GSoC) is an annual global program organized by Google that aims to bring new contributors to the world of open-source. The program pairs organizations (such as the OpenDAL Project) with contributors (usually students), with the goal of helping the participants make meaningful open-source contributions under the guidance of experienced mentors.</p>
<p>Google is sponsoring the <a href="https://summerofcode.withgoogle.com/" target="_blank" rel="noopener noreferrer" class="">2024 Summer of Code</a> and <a href="https://www.apache.org/" target="_blank" rel="noopener noreferrer" class="">The Apache Software Foundation</a> (ASF) registered as a mentoring organization. The GSoC applicants now have several weeks to send project proposals to organizations that appeal to them. If their project proposal is accepted, they will embark on a 12-week journey during which they will try to complete their proposed project under the guidance of an assigned mentor.</p>
<p>We have prepared <a href="https://github.com/apache/opendal/issues/4131" target="_blank" rel="noopener noreferrer" class="">a list of project ideas</a> that can serve as inspiration for potential GSoC contributors that would like to send a project proposal to the OpenDAL project. However, applicants can also come up with their own project ideas. You can discuss project ideas or try to find mentors on the <a href="mailto:dev@opendal.apache.org" target="_blank" rel="noopener noreferrer" class="">maillist</a> or <a href="https://discord.gg/XQy8yGR2dg" target="_blank" rel="noopener noreferrer" class="">Discord</a>. We have also prepared <a href="https://opendal.apache.org/community/events/gsoc-proposal-guide" target="_blank" rel="noopener noreferrer" class="">a proposal guide</a> that should help you with preparing your project proposals.</p>
<p>You can start discussing the project ideas with OpenDAL Project maintainers immediately. The project proposal application period starts on March 18, 2024, and ends on April 2, 2024 at 18:00 UTC. Take note of that deadline, as there will be no extensions!</p>
<p>If you are interested in contributing to the OpenDAL Project, we encourage you to check out our project idea list and send us a GSoC project proposal! Of course, you are also free to discuss these projects and/or try to move them forward even if you do not intend to (or cannot) participate in GSoC. We welcome all contributors to OpenDAL, as there is always enough work to do.</p>
<p>We are excited about this event. Hoping you all feel the same way!</p>
<blockquote>
<p>This announcement is inspired a lot by the <a href="https://blog.rust-lang.org/2024/02/21/Rust-participates-in-GSoC-2024.html" target="_blank" rel="noopener noreferrer" class="">Rust participates in Google Summer of Code 2024</a>.</p>
</blockquote>]]></content:encoded>
            <category>announcement</category>
        </item>
        <item>
            <title><![CDATA[Apache OpenDAL™ is now Graduated]]></title>
            <link>https://opendal.apache.org/blog/apache-opendal-graduated/</link>
            <guid>https://opendal.apache.org/blog/apache-opendal-graduated/</guid>
            <pubDate>Mon, 22 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Hello, everyone! I'm happy to announce that Apache OpenDAL™ has graduated from the Apache Incubator to become a Top-Level Project of the Apache Software Foundation.]]></description>
            <content:encoded><![CDATA[<p>Hello, everyone! I'm happy to announce that <a href="https://opendal.apache.org/" target="_blank" rel="noopener noreferrer" class="">Apache OpenDAL™</a> has graduated from the <a href="https://incubator.apache.org/" target="_blank" rel="noopener noreferrer" class="">Apache Incubator</a> to become a Top-Level Project of <a href="https://apache.org/" target="_blank" rel="noopener noreferrer" class="">the Apache Software Foundation</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="whats-apache-opendal">What's Apache OpenDAL?<a href="https://opendal.apache.org/blog/apache-opendal-graduated/#whats-apache-opendal" class="hash-link" aria-label="Direct link to What's Apache OpenDAL?" title="Direct link to What's Apache OpenDAL?" translate="no">​</a></h2>
<p><strong>Apache OpenDAL</strong> is a data access layer that allows users to easily and efficiently retrieve data from various storage services in a unified way. Our VISION is <strong>access data freely</strong>.</p>
<p>OpenDAL could be used as a <strong>better</strong> SDK for your storage services: A SDK with native integration of <a href="https://opendal.apache.org/docs/rust/opendal/layers/struct.RetryLayer.html" target="_blank" rel="noopener noreferrer" class="">retry</a>, <a href="https://opendal.apache.org/docs/rust/opendal/layers/struct.LoggingLayer.html" target="_blank" rel="noopener noreferrer" class="">logging</a>, <a href="https://opendal.apache.org/docs/rust/opendal/layers/struct.MetricsLayer.html" target="_blank" rel="noopener noreferrer" class="">metrics</a>, <a href="https://opendal.apache.org/docs/rust/opendal/layers/struct.TracingLayer.html" target="_blank" rel="noopener noreferrer" class="">tracing</a>, <a href="https://opendal.apache.org/docs/rust/opendal/layers/struct.TimeoutLayer.html" target="_blank" rel="noopener noreferrer" class="">timeout</a>, <a href="https://opendal.apache.org/docs/rust/opendal/layers/struct.ThrottleLayer.html" target="_blank" rel="noopener noreferrer" class="">throttle</a>, and <a href="https://opendal.apache.org/docs/rust/opendal/layers/index.html" target="_blank" rel="noopener noreferrer" class="">more</a>.</p>
<p>OpenDAL could be used as a <strong>super</strong> connector for your storage services: A connector that supports all kinds of storage services from Object Storage (s3, gcs, azblob), File Storage (fs, azdls, hdfs), Consumer Cloud Storage (gdrive, onedrive), Key-Value Storage (rocksdb, sled) to Cache Storage (memcached, moka).</p>
<p>OpenDAL could be used as an <strong>elegant</strong> client for your storage services: A client with well designed API and  many language bindings: <a href="https://crates.io/crates/opendal" target="_blank" rel="noopener noreferrer" class="">Rust</a>, C, Cpp, Dotnet, Go, Haskell, <a href="https://mvnrepository.com/artifact/org.apache.opendal/opendal-java" target="_blank" rel="noopener noreferrer" class="">Java</a>, Lua, <a href="https://www.npmjs.com/package/opendal" target="_blank" rel="noopener noreferrer" class="">Node.js</a>, OCaml, PHP, <a href="https://pypi.org/project/opendal/" target="_blank" rel="noopener noreferrer" class="">Python</a>, Ruby, Swift and Zig.</p>
<p>Need to access data? Give OpenDAL a try!</p>
<div class="language-rust codeBlockContainer_RtmP theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_Pm3P"><pre tabindex="0" class="prism-code language-rust codeBlock_JK9j thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_ODIi"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Init s3 service.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> builder </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">services</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token constant" style="color:#36acaa">S3</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    builder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">bucket</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"test"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Init an operator</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> op </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Operator</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">via_map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">builder</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// Add logging</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">layer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">LoggingLayer</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">default</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">finish</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Write data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">write</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hello.txt"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Hello, World!"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Read data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> bs </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">read</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hello.txt"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Fetch metadata</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> meta </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stat</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hello.txt"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> mode </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> meta</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">mode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> length </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> meta</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">content_length</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Delete</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">delete</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hello.txt"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="whats-the-asf">What's the ASF?<a href="https://opendal.apache.org/blog/apache-opendal-graduated/#whats-the-asf" class="hash-link" aria-label="Direct link to What's the ASF?" title="Direct link to What's the ASF?" translate="no">​</a></h2>
<p>The Apache Software Foundation (ASF) is a nonprofit corporation to support a number of open-source software projects. The Apache Software Foundation exists to provide software for the public good. We believe in the power of community over code, known as The Apache Way. Thousands of people around the world contribute to ASF open source projects every day.</p>
<p>The OpenDAL Community believes <a href="https://www.apache.org/theapacheway/" target="_blank" rel="noopener noreferrer" class="">the apache way</a> that:</p>
<ul>
<li class=""><em>Earned Authority</em>: all individuals are given the opportunity to participate, but their influence is based on publicly earned merit – what they contribute to the community.</li>
<li class=""><em>Community of Peers</em>: individuals participate at the ASF, not organizations.</li>
<li class=""><em>Open Communications</em>: as a virtual organization, the ASF requires all communications related to code and decision-making to be publicly accessible to ensure asynchronous collaboration, as necessitated by a globally-distributed community.</li>
<li class=""><em>Consensus Decision Making</em>: Apache Projects are overseen by a self-selected team of active volunteers who are contributing to their respective projects.</li>
<li class=""><em>Responsible Oversight</em>: The ASF governance model is based on trust and delegated oversight.</li>
</ul>
<p>The original creators <a href="https://github.com/datafuselabs/databend/" target="_blank" rel="noopener noreferrer" class="">Databend</a> chosen to contribute OpenDAL to the ASF, embracing the Apache way through <a href="https://opendal.apache.org/blog/opendal-entered-apache-incubator" target="_blank" rel="noopener noreferrer" class="">joining the incubator program</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="whats-graduation">What's graduation?<a href="https://opendal.apache.org/blog/apache-opendal-graduated/#whats-graduation" class="hash-link" aria-label="Direct link to What's graduation?" title="Direct link to What's graduation?" translate="no">​</a></h2>
<p>In the <a href="https://incubator.apache.org/" target="_blank" rel="noopener noreferrer" class="">Apache Incubator</a>, the OpenDAL community is learning the Apache Way through daily development activities, growing its community and producing Apache releases.</p>
<p>During the incubation, we:</p>
<ul>
<li class="">Consist of 19 committers, including mentors, with 12 serving as PPMC members.</li>
<li class="">Boast 164 contributors.</li>
<li class="">Made 9 releases—averaging at least one per month.</li>
<li class="">Had 7 different release managers to date.</li>
<li class="">Used by 10 known entities and is a dependency for 263 GitHub projects and 18 crates.io packages.</li>
<li class="">Opened 1,200+ issues with 1,100+ successfully resolved.</li>
<li class="">Submitted a total of 2,400+ PRs, most of them have been merged or closed.</li>
</ul>
<p>The graduation signifies that the OpenDAL Community is recognized as a <a href="https://opendal.apache.org/community/maturity" target="_blank" rel="noopener noreferrer" class="">mature</a> community, which entails:</p>
<ul>
<li class="">CODE: OpenDAL is an <a href="https://github.com/apache/opendal/blob/main/LICENSE" target="_blank" rel="noopener noreferrer" class="">Apache 2.0 licensed</a> open-source project with <a href="https://github.com/apache/opendal" target="_blank" rel="noopener noreferrer" class="">accessible, buildable code</a> on GitHub, featuring <a href="https://github.com/apache/opendal/commits/main/" target="_blank" rel="noopener noreferrer" class="">a traceable history and authenticated code provenance</a>.</li>
<li class="">LICENSE: OpenDAL maintains <a href="https://github.com/apache/opendal/blob/main/DEPENDENCIES.md" target="_blank" rel="noopener noreferrer" class="">open-source compliance</a> for all code and dependencies, requires contributor agreements, and clearly documents copyright ownership.</li>
<li class="">Releases: OpenDAL offers standardized, committee-approved <a href="https://downloads.apache.org/opendal/" target="_blank" rel="noopener noreferrer" class="">source code releases</a> with secure signatures, provides convenience binaries, and has <a href="https://opendal.apache.org/community/committers/release" target="_blank" rel="noopener noreferrer" class="">a well-documented, repeatable release process</a>.</li>
<li class="">Quality: OpenDAL is committed to code quality transparency, prioritizes security with quick issue responses, ensures backward compatibility with clear documentation, and actively addresses bug reports in a timely manner.</li>
<li class="">Community: OpenDAL offers <a href="https://opendal.apache.org/" target="_blank" rel="noopener noreferrer" class="">a comprehensive homepage</a>, welcomes diverse contributions, promotes a meritocratic approach for active contributors, operates on community consensus, and ensures timely responses to user queries through various channels.</li>
<li class="">Consensus: OpenDAL has a <a href="https://projects.apache.org/committee.html?opendal" target="_blank" rel="noopener noreferrer" class="">public list of key decision-makers</a> and uses a consensus approach for decisions, documented on its <a href="https://lists.apache.org/list.html?dev@opendal.apache.org" target="_blank" rel="noopener noreferrer" class="">main communication channel</a>. It follows standard voting rules and records all important discussions in writing.</li>
<li class="">Independence: OpenDAL is independent, with contributors from various companies acting on their own, not as representatives of any organization.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="whats-next">What's next?<a href="https://opendal.apache.org/blog/apache-opendal-graduated/#whats-next" class="hash-link" aria-label="Direct link to What's next?" title="Direct link to What's next?" translate="no">​</a></h2>
<p>After graduation, OpenDAL Community will continue to focus on the following aspects under the VISION: <strong>access data freely</strong>.</p>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="more-stable-services">More Stable Services<a href="https://opendal.apache.org/blog/apache-opendal-graduated/#more-stable-services" class="hash-link" aria-label="Direct link to More Stable Services" title="Direct link to More Stable Services" translate="no">​</a></h3>
<p>OpenDAL now supports 59 services, although only some of them are <em>stable</em>.</p>
<p><em>stable</em> for OpenDAL means that</p>
<ul>
<li class="">Have integration tests covered.</li>
<li class="">Have at least one production user.</li>
</ul>
<p>The <em>stable</em> service established a feedback loop between the OpenDAL community and its users. Users can submit bug reports or feature requests to the OpenDAL community, which in turn can enhance the service using this feedback while ensuring existing features remain intact.</p>
<p>After graduation, the OpenDAL community will focus on improving the stability of current services instead of just expanding our offerings.</p>
<p>We plan to:</p>
<ul>
<li class="">Add features users wanted to services like <a href="https://github.com/apache/opendal/issues/2611" target="_blank" rel="noopener noreferrer" class="">file version</a>, <a href="https://github.com/apache/opendal/issues/3977" target="_blank" rel="noopener noreferrer" class="">concurrently list</a> and <a href="https://github.com/apache/opendal/issues/1251" target="_blank" rel="noopener noreferrer" class="">glob pattern</a>.</li>
<li class="">Add integration tests for newly added services.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="more-useful-documents">More Useful Documents<a href="https://opendal.apache.org/blog/apache-opendal-graduated/#more-useful-documents" class="hash-link" aria-label="Direct link to More Useful Documents" title="Direct link to More Useful Documents" translate="no">​</a></h3>
<p>OpenDAL have good docs for its rust core, but not for other language bindings.</p>
<p>The lack of comprehensive documentation makes OpenDAL challenging for users to operate in Java or Python. Without user feedback, the community is unable to enhance this documentation, leading to a detrimental cycle that must be broken.</p>
<p>After graduation, the OpenDAL community will improve the documentation of other language bindings.</p>
<p>We plan to:</p>
<ul>
<li class="">Introduce code generation to automatically create documentation for the service builder due to its numerous configurations.</li>
<li class="">Add more API Docs and examples for other language bindings.</li>
</ul>
<p>OpenDAL have good docs for its public API, but not for its internal design.</p>
<p>OpenDAL is proud of its elegant design, but it is not well documented. This makes it difficult for new contributors to understand the codebase and make contributions.</p>
<p>After graduation, the OpenDAL community will improve the documentation of its internal design.</p>
<p>We plan to:</p>
<ul>
<li class="">Optimize the codebase to make it easier to understand.</li>
<li class="">Add more blog posts to explain the design of OpenDAL.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="more-production-users">More Production Users<a href="https://opendal.apache.org/blog/apache-opendal-graduated/#more-production-users" class="hash-link" aria-label="Direct link to More Production Users" title="Direct link to More Production Users" translate="no">​</a></h3>
<p>OpenDAL requires more production users, as they are vital to the success of our project. Increased user production leads to more valuable feedback, a more engaged contributor base, and a stronger community. We've started the initial loop; let's expand it!</p>
<p>After graduation, the OpenDAL community will focus on attracting more production users.</p>
<p>We plan to:</p>
<ul>
<li class="">Optimize the feature set for adoption like <a href="https://github.com/apache/opendal/issues/3022" target="_blank" rel="noopener noreferrer" class="">uri initiation</a> and <a href="https://github.com/apache/opendal/issues/3240" target="_blank" rel="noopener noreferrer" class="">config</a>.</li>
<li class="">Expand more ways to use OpenDAL via <a href="https://github.com/apache/opendal/tree/main/bin/ofs" target="_blank" rel="noopener noreferrer" class="">fuse</a>, <a href="https://github.com/apache/opendal/tree/main/bin/oli" target="_blank" rel="noopener noreferrer" class="">cli</a>, <a href="https://github.com/apache/opendal/tree/main/bin/oli" target="_blank" rel="noopener noreferrer" class="">S3/WebDAV API</a>, <a href="https://github.com/apache/opendal/tree/main/integrations/object_store" target="_blank" rel="noopener noreferrer" class="">object_store binding</a>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="conclusion">Conclusion<a href="https://opendal.apache.org/blog/apache-opendal-graduated/#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>The OpenDAL Community aims to create a world where users can freely access data across any storage service in any manner they choose. Graduation is just the beginning—let's work together to make our VISION a reality!</p>]]></content:encoded>
            <category>announcement</category>
        </item>
        <item>
            <title><![CDATA[OwO #1: The v0.40 Release]]></title>
            <link>https://opendal.apache.org/blog/owo-1/</link>
            <guid>https://opendal.apache.org/blog/owo-1/</guid>
            <pubDate>Fri, 15 Sep 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[OwO (Outcome, Working, Outlook) is an Apache OpenDAL™ release blog series, where we share the current work status and future plans.]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>OwO (Outcome, Working, Outlook) is an Apache OpenDAL™ release blog series, where we share the current work status and future plans.</p>
</blockquote>
<p>Hello! It's been a while since our last update. We've been hard at work determining the optimal way to implement new features and improvements. We're thrilled to announce that we'll soon be releasing v0.40.</p>
<p>This post is structured into three main sections:</p>
<ul>
<li class="">Outcome (1st <code>O</code> in <code>OwO</code>): Summarizes the key accomplishments in the v0.40 release.</li>
<li class="">Working (the <code>w</code> in <code>OwO</code>): Provides an update on our current work.</li>
<li class="">Outlook (2nd <code>O</code> in <code>OwO</code>): Discusses what lies ahead for OpenDAL.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="outcome">Outcome<a href="https://opendal.apache.org/blog/owo-1/#outcome" class="hash-link" aria-label="Direct link to Outcome" title="Direct link to Outcome" translate="no">​</a></h2>
<p>OpenDAL now comprises four primary components:</p>
<ul>
<li class="">Core: The core library written in Rust.</li>
<li class="">Bindings: Language bindings powered by the OpenDAL Rust core.</li>
<li class="">Applications: Applications built using the OpenDAL Rust core.</li>
<li class="">Integrations: Collaborations with other projects.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="core">Core<a href="https://opendal.apache.org/blog/owo-1/#core" class="hash-link" aria-label="Direct link to Core" title="Direct link to Core" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="unifying-append-and-write-functions">Unifying Append and Write Functions<a href="https://opendal.apache.org/blog/owo-1/#unifying-append-and-write-functions" class="hash-link" aria-label="Direct link to Unifying Append and Write Functions" title="Direct link to Unifying Append and Write Functions" translate="no">​</a></h4>
<p>OpenDAL has supported <code>append</code> operations since <code>v0.36</code>. We've found, however, that this led to significant duplication between append and write. As a result, we've streamlined the two functionalities into a single write function. Our users can now:</p>
<div class="language-rust codeBlockContainer_RtmP theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_Pm3P"><pre tabindex="0" class="prism-code language-rust codeBlock_JK9j thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_ODIi"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> w </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">writer_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"test.txt"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">append</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">write</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">content_a</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">write</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">content_b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">w</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>This way, users can reuse the <code>Writer</code> in their own logic without handling <code>append</code> separately.</p>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="new-lister-api">New Lister API<a href="https://opendal.apache.org/blog/owo-1/#new-lister-api" class="hash-link" aria-label="Direct link to New Lister API" title="Direct link to New Lister API" translate="no">​</a></h4>
<p>To improve API consistency, we've made some adjustments to our listing functions. We've added <code>list</code> and <code>list_with</code> methods that perform single operations and renamed the original <code>list</code> to <code>lister</code> and <code>lister_with</code>.</p>
<div class="language-rust codeBlockContainer_RtmP theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_Pm3P"><pre tabindex="0" class="prism-code language-rust codeBlock_JK9j thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_ODIi"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// Old API</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> lister</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Lister</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">list</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"dir"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// New API</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> entries</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Vec</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Entry</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">list</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"dir"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> lister</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Lister</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">lister</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"dir"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>This brings uniformity to our API offerings.</p>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="list-with-metakey">List With Metakey<a href="https://opendal.apache.org/blog/owo-1/#list-with-metakey" class="hash-link" aria-label="Direct link to List With Metakey" title="Direct link to List With Metakey" translate="no">​</a></h4>
<p>To speed up list operations, OpenDAL can now fetch and store metadata during the listing process. This eliminates the need for separate metadata calls:</p>
<div class="language-rust codeBlockContainer_RtmP theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_Pm3P"><pre tabindex="0" class="prism-code language-rust codeBlock_JK9j thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_ODIi"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> entries</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Vec</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Entry</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> op</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">list_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"dir/"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">metakey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Metakey</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">ContentLength</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token class-name">Metakey</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">ContentType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Use the metadata directly!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> meta</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token class-name">Metadata</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> entries</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">metadata</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>This makes metadata retrieval more intuitive.</p>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="buffered-writer">Buffered Writer<a href="https://opendal.apache.org/blog/owo-1/#buffered-writer" class="hash-link" aria-label="Direct link to Buffered Writer" title="Direct link to Buffered Writer" translate="no">​</a></h4>
<p>We've added general buffer support to optimize writing operations.</p>
<div class="language-rust codeBlockContainer_RtmP theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_Pm3P"><pre tabindex="0" class="prism-code language-rust codeBlock_JK9j thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_ODIi"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> w </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">writer_with</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"path/to/file"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buffer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">8</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1024</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1024</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">await</span><span class="token operator" style="color:#393A34">?</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="others">Others<a href="https://opendal.apache.org/blog/owo-1/#others" class="hash-link" aria-label="Direct link to Others" title="Direct link to Others" translate="no">​</a></h4>
<p>Other improvements in the core library can be found in our <a href="https://github.com/apache/opendal/blob/main/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="">CHANGELOG</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="bindings">Bindings<a href="https://opendal.apache.org/blog/owo-1/#bindings" class="hash-link" aria-label="Direct link to Bindings" title="Direct link to Bindings" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="c">C++<a href="https://opendal.apache.org/blog/owo-1/#c" class="hash-link" aria-label="Direct link to C++" title="Direct link to C++" translate="no">​</a></h4>
<p><a href="https://github.com/apache/opendal/tree/main/bindings/cpp" target="_blank" rel="noopener noreferrer" class=""><code>opendal-cpp</code></a> is ready for its first release! Welcome to check it out and give us some feedback.</p>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="haskell">Haskell<a href="https://opendal.apache.org/blog/owo-1/#haskell" class="hash-link" aria-label="Direct link to Haskell" title="Direct link to Haskell" translate="no">​</a></h4>
<p><a href="https://github.com/apache/opendal/tree/main/bindings/haskell" target="_blank" rel="noopener noreferrer" class=""><code>opendal-hs</code></a> is ready for its first release! Welcome to check it out and give us some feedback.</p>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="java">Java<a href="https://opendal.apache.org/blog/owo-1/#java" class="hash-link" aria-label="Direct link to Java" title="Direct link to Java" translate="no">​</a></h4>
<p><a href="https://github.com/apache/opendal/tree/main/bindings/java" target="_blank" rel="noopener noreferrer" class=""><code>opendal-java</code></a> enabled more available services in this release, allowing user to visit services like <code>redis</code> that not enabled by default in rust core. And <code>opendal-java</code> enabled blocking layer to allow users visit services like <code>s3</code> in blocking way.</p>
<p>Welcome to integrate <code>opendal-java</code> into your project and give us some feedback.</p>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="new-bindings">New bindings!<a href="https://opendal.apache.org/blog/owo-1/#new-bindings" class="hash-link" aria-label="Direct link to New bindings!" title="Direct link to New bindings!" translate="no">​</a></h4>
<ul>
<li class=""><a href="https://github.com/apache/opendal/tree/main/bindings/dotnet" target="_blank" rel="noopener noreferrer" class=""><code>opendal-dotnet</code></a></li>
<li class=""><a href="https://github.com/apache/opendal/tree/main/bindings/php" target="_blank" rel="noopener noreferrer" class=""><code>opendal-php</code></a></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="applications">Applications<a href="https://opendal.apache.org/blog/owo-1/#applications" class="hash-link" aria-label="Direct link to Applications" title="Direct link to Applications" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="oay">oay<a href="https://opendal.apache.org/blog/owo-1/#oay" class="hash-link" aria-label="Direct link to oay" title="Direct link to oay" translate="no">​</a></h4>
<p><a href="https://github.com/apache/opendal/tree/main/bin/oay" target="_blank" rel="noopener noreferrer" class="">oay</a> is OpenDAL Gateway that allows users to access OpenDAL services via existing protocols like <code>s3</code> and <code>webdav</code>. It works like a proxy that forwarding requests to OpenDAL services.</p>
<p>In this release, we implement basic <code>webdav</code> support. Users can convert any storage services to a webdav server!</p>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="oli">oli<a href="https://opendal.apache.org/blog/owo-1/#oli" class="hash-link" aria-label="Direct link to oli" title="Direct link to oli" translate="no">​</a></h4>
<p><a href="https://github.com/apache/opendal/tree/main/bin/oay" target="_blank" rel="noopener noreferrer" class="">oli</a> is OpenDAL CLI that allows users to access storage services via CLI like <code>s3cmd</code> and <code>gcloud</code> does.</p>
<p>We fixed some experience issues in this release and improved some docs. Welcome to try it out and give us some feedback.</p>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="integrations">Integrations<a href="https://opendal.apache.org/blog/owo-1/#integrations" class="hash-link" aria-label="Direct link to Integrations" title="Direct link to Integrations" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_L3BC" id="object_store">object_store<a href="https://opendal.apache.org/blog/owo-1/#object_store" class="hash-link" aria-label="Direct link to object_store" title="Direct link to object_store" translate="no">​</a></h4>
<p><a href="https://github.com/apache/opendal/tree/main/integrations/object_store" target="_blank" rel="noopener noreferrer" class="">object_store</a> instead to implement <a href="https://github.com/apache/arrow-rs/tree/master/object_store" target="_blank" rel="noopener noreferrer" class=""><code>object_store</code></a>'s trait over OpenDAL Operator so that users can use OpenDAL as a backend for <code>object_store</code>.</p>
<p><code>object_store</code> is mostly functional, but there are some edge use cases that OpenDAL has yet to support.</p>
<p>So far, this release hasn't seen progress in this area; we are awaiting the resolution of the issue <a href="https://github.com/apache/opendal/issues/2762" target="_blank" rel="noopener noreferrer" class="">Allow list paths that do not end with <code>/</code></a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="working">Working<a href="https://opendal.apache.org/blog/owo-1/#working" class="hash-link" aria-label="Direct link to Working" title="Direct link to Working" translate="no">​</a></h2>
<p>We are working on the following things:</p>
<ul>
<li class=""><code>object_store</code> support: Make <code>object_store</code> integration works and find a user for it.</li>
<li class="">Remove the <code>/</code> limitation for path, so we can list a path without ending with <code>/</code>.</li>
<li class="">Expand the <code>start-after</code> support to more services (Address <a href="https://github.com/apache/opendal/issues/2786" target="_blank" rel="noopener noreferrer" class="">#2786</a>).</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="outlook">Outlook<a href="https://opendal.apache.org/blog/owo-1/#outlook" class="hash-link" aria-label="Direct link to Outlook" title="Direct link to Outlook" translate="no">​</a></h2>
<p>We are exploring some innovative ideas:</p>
<ul>
<li class=""><a href="https://github.com/apache/opendal/discussions/2951" target="_blank" rel="noopener noreferrer" class="">OpenDAL REST/gRPC API</a>: A REST/gRPC Server for OpenDAL.</li>
<li class=""><a href="https://github.com/apache/opendal/discussions/2953" target="_blank" rel="noopener noreferrer" class="">OpenDAL Cache</a>: OpenDAL native cache libs that allowing users to access data more efficiently.</li>
<li class=""><a href="https://github.com/apache/opendal/discussions/2952" target="_blank" rel="noopener noreferrer" class="">OpenDAL File System</a>: A read-only file system that built upon OpenDAL in rust!</li>
<li class=""><a href="https://github.com/apache/opendal/discussions/3042" target="_blank" rel="noopener noreferrer" class="">kio-opendal</a>: A kio plugin powered by OpenDAL that allows users to visit different storage services in <a href="https://apps.kde.org/dolphin/" target="_blank" rel="noopener noreferrer" class="">KDE Dolphin</a>.</li>
<li class="">gvfs-opendal: A gvfs plugin powered by OpenDAL that allows users to visit different storage services in <a href="https://wiki.gnome.org/Apps/Files" target="_blank" rel="noopener noreferrer" class="">GNOME Files</a></li>
</ul>
<p>Feel free to join in the discussion!</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="summary">Summary<a href="https://opendal.apache.org/blog/owo-1/#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>This marks our first OpenDAL <code>OwO</code> post. We welcome your feedback.</p>]]></content:encoded>
            <category>owo</category>
        </item>
        <item>
            <title><![CDATA[Apache OpenDAL™ Internal: Data Reading]]></title>
            <link>https://opendal.apache.org/blog/how-opendal-read-data/</link>
            <guid>https://opendal.apache.org/blog/how-opendal-read-data/</guid>
            <pubDate>Tue, 15 Aug 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[The first article will discuss OpenDAL's most commonly used data reading function. I will start from the outermost interface and then gradually unfold according to the calling sequence of OpenDAL.]]></description>
            <content:encoded><![CDATA[<p>As the Apache OpenDAL™ community continues to grow, new abstractions are constantly being added, which has brought some burdens to new contributors participating in development. Many maintainers hope to have a deeper understanding of OpenDAL's internal implementation. At the same time, OpenDAL's core design has not changed significantly for a long time, making it possible to write a series on internal implementation. I believe now is the time to write a series of articles on OpenDAL's internal implementation, to explain from the maintainer's perspective how OpenDAL is designed, implemented, and how it can be expanded. With the impending release of OpenDAL v0.40, I hope this series of articles will better help the community understand the past, master the present, and shape the future.</p>
<p>The first article will discuss OpenDAL's most commonly used data reading function. I will start from the outermost interface and then gradually unfold according to the calling sequence of OpenDAL. Let's get started!</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="overall-framework">Overall Framework<a href="https://opendal.apache.org/blog/how-opendal-read-data/#overall-framework" class="hash-link" aria-label="Direct link to Overall Framework" title="Direct link to Overall Framework" translate="no">​</a></h2>
<p>Before starting to introduce the specific OpenDAL interface, let's first get familiar with the OpenDAL project.</p>
<p><a href="https://github.com/apache/opendal" target="_blank" rel="noopener noreferrer" class="">OpenDAL</a> is an Apache Incubator project aimed at helping users access data from various storage services in a unified, convenient, and efficient way. Its project <a href="https://opendal.apache.org/vision" target="_blank" rel="noopener noreferrer" class="">vision</a> is "free access to data":</p>
<ul>
<li class="">Free from services: Any service can be accessed freely through native interfaces</li>
<li class="">Free from implementations: No matter how the underlying implementation is, it can be called in a unified way</li>
<li class="">Free to integrate: Able to freely integrate with various services and languages</li>
<li class="">Free to zero cost: Users don't have to pay for features they don't use</li>
</ul>
<p>On this philosophical foundation, OpenDAL Rust Core can be mainly divided into the following components:</p>
<ul>
<li class="">Operator: The outer interface exposed to users</li>
<li class="">Layers: Specific implementation of different middleware</li>
<li class="">Services: Specific implementation of different services</li>
</ul>
<p>From a macroscopic perspective, OpenDAL's data reading call stack would look like this:</p>
<p><img decoding="async" loading="lazy" src="https://opendal.apache.org/assets/images/1-0b02956a3da2b4329eab11ea4779711c.png" width="1238" height="968" class="img_EjcX"></p>
<p>All Layers and Services have implemented a unified Accessor interface, erasing all type information when building the Operator. For the Operator, regardless of what services are used or how many middleware are added, all call logic is consistent. This design splits OpenDAL's API into Public API and Raw API, where the Public API is directly exposed to users, providing convenient top-level interfaces, and Raw API is provided to OpenDAL internal developers, maintaining a unified internal interface and providing some convenient implementation.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="operator">Operator<a href="https://opendal.apache.org/blog/how-opendal-read-data/#operator" class="hash-link" aria-label="Direct link to Operator" title="Direct link to Operator" translate="no">​</a></h2>
<p>OpenDAL's Operator API will adhere to a consistent calling paradigm as much as possible, reducing users' learning and usage costs. For example, OpenDAL offers the following APIs for <code>read</code>:</p>
<ul>
<li class=""><code>op.read(path)</code>: Reads the entire content of the specified file</li>
<li class=""><code>op.reader(path)</code>: Creates a Reader for streaming reading</li>
<li class=""><code>op.read_with(path).range(1..1024)</code>: Reads file content using specified parameters, such as range</li>
<li class=""><code>op.reader_with(path).range(1..1024)</code>: Creates a Reader for streaming reading with specified parameters</li>
</ul>
<p>It's not hard to see that <code>read</code> is more like syntactic sugar, allowing users to quickly read files without considering various traits like <code>AsyncRead</code>. The <code>reader</code> provides more flexibility, implementing widely-used community traits like <code>AsyncSeek</code>, <code>AsyncRead</code>, allowing more flexible data reading. <code>read_with</code> and <code>reader_with</code> assist users in specifying various parameters in a more natural way through Future Builder functions.</p>
<p>The internal logic of the Operator would look like this:</p>
<p><img decoding="async" loading="lazy" src="https://opendal.apache.org/assets/images/2-3b83ca1ebfbdd77770566a80131846bd.png" width="1628" height="1006" class="img_EjcX"></p>
<p>Its main job is to encapsulate the interface for the user:</p>
<ul>
<li class="">Completing the construction of <code>OpRead</code>: the args for read operation.</li>
<li class="">Calling the <code>read</code> function provided by <code>Accessor</code></li>
<li class="">Wrapping the returned value as <code>Reader</code> and implementing interfaces like <code>AsyncSeek</code>, <code>AsyncRead</code>, etc., based on <code>Reader</code></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="layers">Layers<a href="https://opendal.apache.org/blog/how-opendal-read-data/#layers" class="hash-link" aria-label="Direct link to Layers" title="Direct link to Layers" translate="no">​</a></h2>
<p>A little secret here is that OpenDAL will automatically apply some Layers to the Service to implement some internal logic. As of the completion of this article, OpenDAL's automatically added Layers include:</p>
<ul>
<li class=""><code>ErrorContextLayer</code>: Injects context information, such as <code>scheme</code>, <code>path</code>, etc., into all returned errors of Operation</li>
<li class=""><code>CompleteLayer</code>: Adds necessary capabilities to services, such as adding seek support to s3</li>
<li class=""><code>TypeEraseLayer</code>: Implements type erasure, uniformly erasing associated types in <code>Accessor</code>, so users don't need to carry generic parameters when using it</li>
</ul>
<p>Here, <code>ErrorContextLayer</code> and <code>TypeEraseLayer</code> are relatively simple and won't be elaborated on. The focus is on <code>CompleteLayer</code>, aimed at adding <code>seek</code> or <code>next</code> support to OpenDAL's returned <code>Reader</code> in a zero-cost way, so users don't have to re-implement it. OpenDAL initially returned <code>Reader</code> and <code>SeekableReader</code> through different function calls in early versions, but the actual user feedback was not very good; almost all users were using <code>SeekableReader</code>. Therefore, OpenDAL subsequently added seek support as the first priority to the internal <code>Read</code> trait during the refactor:</p>
<div class="language-rust codeBlockContainer_RtmP theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_Pm3P"><pre tabindex="0" class="prism-code language-rust codeBlock_JK9j thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_ODIi"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">trait</span><span class="token plain"> </span><span class="token type-definition class-name">Read</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Unpin</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">Send</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">Sync</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Read bytes asynchronously.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">poll_read</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> cx</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token class-name">Context</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'_</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> buf</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">u8</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Poll</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">usize</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Seek asynchronously.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">///</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Returns `Unsupported` error if underlying reader doesn't support seek.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">poll_seek</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> cx</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token class-name">Context</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'_</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pos</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">io</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">SeekFrom</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Poll</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">u64</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Stream [`Bytes`] from underlying reader.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">///</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Returns `Unsupported` error if underlying reader doesn't support stream.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">///</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// This API exists for avoiding bytes copying inside async runtime.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// Users can poll bytes from underlying reader and decide when to</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// read/consume them.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">poll_next</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> cx</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token class-name">Context</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token lifetime-annotation symbol" style="color:#36acaa">'_</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Poll</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Bytes</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>To implement a service's reading capability in OpenDAL, one needs to implement this trait, which is an internal interface and will not be directly exposed to users. Among them:</p>
<ul>
<li class=""><code>poll_read</code> is the most basic requirement; all services must implement this interface.</li>
<li class="">When the service natively supports <code>seek</code>, <code>poll_seek</code> can be implemented, and OpenDAL will correctly dispatch, such as local fs;</li>
<li class="">When the service natively supports <code>next</code>, meaning it returns streaming Bytes, <code>poll_next</code> can be implemented, like HTTP-based services, where the underlying layer is a TCP Stream, and hyper will encapsulate it as a bytes stream.</li>
</ul>
<p>Through the <code>Read</code> trait, OpenDAL ensures that all services can expose their native support capabilities as much as possible, thereby achieving efficient reading for different services.</p>
<p>Based on this trait, OpenDAL will complete according to the capabilities supported by each service:</p>
<ul>
<li class="">Both seek/next are supported: Direct return</li>
<li class="">No support for next: Encapsulate using <code>StreamableReader</code> to simulate next support</li>
<li class="">No support for seek: Encapsulate using <code>ByRangeSeekableReader</code> to simulate seek support</li>
<li class="">Neither seek/next supported: Encapsulate using both methods</li>
</ul>
<blockquote>
<p><code>ByRangeSeekableReader</code> mainly utilizes the service's ability to support range read, dropping the current reader when the user seeks and initiating a new request at the specified location.</p>
</blockquote>
<p>OpenDAL exposes a unified Reader implementation through <code>CompleteLayer</code>, so users don't have to worry about whether the underlying service supports seek; OpenDAL will always choose the optimal way to initiate the request.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="services">Services<a href="https://opendal.apache.org/blog/how-opendal-read-data/#services" class="hash-link" aria-label="Direct link to Services" title="Direct link to Services" translate="no">​</a></h2>
<p>After the completion of the Layers, it's time to call the specific implementation of the Service. Here, the most common services <code>fs</code> and <code>s3</code> are used as examples to explain how data is read.</p>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="service-fs">Service fs<a href="https://opendal.apache.org/blog/how-opendal-read-data/#service-fs" class="hash-link" aria-label="Direct link to Service fs" title="Direct link to Service fs" translate="no">​</a></h3>
<p><code>tokio::fs::File</code> implements <code>tokio::AsyncRead</code> and <code>tokio::AsyncSeek</code>. Using <code>async_compat::Compat</code>, we have transformed it into <code>futures::AsyncRead</code> and <code>futures::AsyncSeek</code>. Based on this, we provide a built-in function <code>oio::into_read_from_file</code> to transform it into a type that implements <code>oio::Read</code>.</p>
<p>There's nothing particularly complex in the implementation of <code>oio::into_read_from_file</code>; read and seek are mostly calling the functions provided by the incoming File type. The tricky part is about the correct handling of seek and range: seeking to the right side of the range is allowed, and this will not cause an error, and reading will only return empty, but seeking to the left side of the range is illegal, and the Reader must return <code>InvalidInput</code> for proper upper-level handling.</p>
<blockquote>
<p>Interesting history: there was <a href="https://github.com/apache/opendal/issues/2717" target="_blank" rel="noopener noreferrer" class="">an issue</a> in the initial implementation of this part, discovered during fuzz testing.</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="services-s3">Services s3<a href="https://opendal.apache.org/blog/how-opendal-read-data/#services-s3" class="hash-link" aria-label="Direct link to Services s3" title="Direct link to Services s3" translate="no">​</a></h3>
<p>S3 is an HTTP-based service, and opendal provides a lot of HTTP-based wrappers to help developers reuse logic; they only need to build a request and return a well-constructed Body. OpenDAL Raw API encapsulates a set of reqwest-based interfaces, and the HTTP GET interface returns a <code>Response&lt;IncomingAsyncBody&gt;</code>:</p>
<div class="language-rust codeBlockContainer_RtmP theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_Pm3P"><pre tabindex="0" class="prism-code language-rust codeBlock_JK9j thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_ODIi"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/// IncomingAsyncBody carries the content returned by remote servers.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">pub</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">IncomingAsyncBody</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// # TODO</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">///</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// hyper returns `impl Stream&lt;Item = crate::Result&lt;Bytes&gt;&gt;` but we can't</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// write the types in stable. So we will box here.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">///</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// After [TAIT](https://rust-lang.github.io/rfcs/2515-type_alias_impl_trait.html)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/// has been stable, we can change `IncomingAsyncBody` into `IncomingAsyncBody&lt;S&gt;`.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    inner</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">oio</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Streamer</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    size</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">u64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    consumed</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    chunk</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Option</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">Bytes</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>The stream contained in this body is the bytes stream returned by reqwest, and opendal implements content length checks and read support on this basis.</p>
<p>Here's an extra note about a small pitfall with reqwest/hyper: reqwest and hyper do not check the returned content length, so an illegal server may return a data volume that does not match the expected content length instead of an error, leading to unexpected data behavior. OpenDAL specifically added checks here, returning <code>ContentIncomplete</code> when data is insufficient and <code>ContentTruncated</code> when data exceeds expectations, avoiding users receiving illegal data.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="conclusion">Conclusion<a href="https://opendal.apache.org/blog/how-opendal-read-data/#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>This article introduces from top to bottom how OpenDAL implements data reading:</p>
<ul>
<li class="">Operator is responsible for exposing user-friendly interfaces</li>
<li class="">Layers are responsible for completing the capabilities of the services</li>
<li class="">Services are responsible for the specific implementation of different services</li>
</ul>
<p>Throughout the entire chain, OpenDAL adheres as much as possible to the principle of zero cost, prioritizing the use of native service capabilities, then considering simulation through other methods, and finally returning unsupported errors. Through this three-tier design, users don't need to understand the details of the underlying service, nor do they need to integrate different service SDKs to easily call <code>op.read(path)</code> to access data in any storage service.</p>
<p>This is: How <strong>OpenDAL</strong> read data freely!</p>]]></content:encoded>
            <category>internal</category>
        </item>
        <item>
            <title><![CDATA[Apache OpenDAL™: Access Data Freely]]></title>
            <link>https://opendal.apache.org/blog/opendal-access-data-freely/</link>
            <guid>https://opendal.apache.org/blog/opendal-access-data-freely/</guid>
            <pubDate>Fri, 07 Jul 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[If you're committed to building cloud-native, cross-cloud-first applications and services, or you want to support configurable storage backends to meet complex data access needs, or if you're tired of juggling various SDKs and hoping for a unified abstraction and development experience, Apache OpenDAL™ will be your perfect partner.]]></description>
            <content:encoded><![CDATA[<p>If you're committed to building cloud-native, cross-cloud-first applications and services, or you want to support configurable storage backends to meet complex data access needs, or if you're tired of juggling various SDKs and hoping for a unified abstraction and development experience, Apache OpenDAL™ will be your perfect partner.</p>
<p><img decoding="async" loading="lazy" alt="OpenDAL Arch" src="https://opendal.apache.org/assets/images/opendal-arch-a614dff17a53ecef1fdbedb43be31c13.png" width="3932" height="2662" class="img_EjcX"></p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="what-is-opendal">What is OpenDAL?<a href="https://opendal.apache.org/blog/opendal-access-data-freely/#what-is-opendal" class="hash-link" aria-label="Direct link to What is OpenDAL?" title="Direct link to What is OpenDAL?" translate="no">​</a></h2>
<p><strong>OpenDAL</strong> is a data access layer that allows users to easily and efficiently retrieve data from various storage services in a unified way.</p>
<p><strong>Data Access Layer</strong> means: OpenDAL is in a critical position in the data read-write process. We shield the implementation details of different storage backends and provide a set of unified interface abstractions externally.</p>
<p>Next, let's try to answer <em>"What OpenDAL is not"</em> and deconstruct OpenDAL from another perspective:</p>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="opendal-is-not-a-proxy-service">Opendal Is Not a Proxy Service<a href="https://opendal.apache.org/blog/opendal-access-data-freely/#opendal-is-not-a-proxy-service" class="hash-link" aria-label="Direct link to Opendal Is Not a Proxy Service" title="Direct link to Opendal Is Not a Proxy Service" translate="no">​</a></h3>
<p>OpenDAL is provided in the form of a library, not as a service or application that proxies various storage backends.</p>
<p>If you want to integrate OpenDAL into an existing project, you need to call OpenDAL's interface directly through the bindings supported by OpenDAL to access the storage services.</p>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="opendal-is-not-an-sdk-aggregator">Opendal Is Not an SDK Aggregator<a href="https://opendal.apache.org/blog/opendal-access-data-freely/#opendal-is-not-an-sdk-aggregator" class="hash-link" aria-label="Direct link to Opendal Is Not an SDK Aggregator" title="Direct link to Opendal Is Not an SDK Aggregator" translate="no">​</a></h3>
<p>Although OpenDAL replaces various SDKs in the application architecture, it is not implemented as an SDK aggregator.</p>
<p>In other words, OpenDAL does not simply call various storage service SDKs. We have developed our own docking with various storage services based on a unified Rust core to ensure that the differences between services are smoothed out.</p>
<p>For example, for S3, OpenDAL manually constructs HTTP requests and parses HTTP responses to ensure that all behaviors comply with API specifications and are fully under the control of OpenDAL. Due to OpenDAL's native takeover of the data access process, we can easily implement unified retry and logging mechanisms for various storage backends and ensure behavioral consistency.</p>
<p>For compatible services with S3, due to the limitations of native storage services and differences in API implementation, compatibility and behavioral details may differ from S3. For example, OSS needs to set an independent header to ensure consistent behavior for <code>Range</code>. In addition to docking with native storage services, OpenDAL will also perform targeted processing for compatible services to ensure users' data access experience.</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="advantages-of-opendal">Advantages of OpenDAL<a href="https://opendal.apache.org/blog/opendal-access-data-freely/#advantages-of-opendal" class="hash-link" aria-label="Direct link to Advantages of OpenDAL" title="Direct link to Advantages of OpenDAL" translate="no">​</a></h2>
<p>OpenDAL is not the only project dedicated to providing data access abstraction, but compared to other similar projects, OpenDAL has the following advantages:</p>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="rich-service-support">Rich Service Support<a href="https://opendal.apache.org/blog/opendal-access-data-freely/#rich-service-support" class="hash-link" aria-label="Direct link to Rich Service Support" title="Direct link to Rich Service Support" translate="no">​</a></h3>
<p>OpenDAL supports dozens of storage services, covering a wide range of scenarios and supporting on-demand selection:</p>
<ul>
<li class="">Standard Storage Protocols: FTP, HTTP, SFTP, WebDAV, etc.</li>
<li class="">Object Storage Services: azblob, gcs, obs, oss, s3, etc.</li>
<li class="">File Storage Services: fs, azdls, hdfs, webhdfs, ipfs, etc.</li>
<li class="">Consumer Cloud Storage Service: Google Drive, OneDrive, Dropbox, etc.</li>
<li class="">Key-Value Storage Service: Memory, Redis, Rocksdb, etc.</li>
<li class="">Cache Storage Service: Ghac, Memcached, etc.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="complete-cross-language-bindings">Complete Cross-Language Bindings<a href="https://opendal.apache.org/blog/opendal-access-data-freely/#complete-cross-language-bindings" class="hash-link" aria-label="Direct link to Complete Cross-Language Bindings" title="Direct link to Complete Cross-Language Bindings" translate="no">​</a></h3>
<p>With Rust as the core, OpenDAL now provides binding support for multiple languages such as Python/Node.js/Java/C and is also actively developing bindings for other languages.</p>
<p>Cross-language bindings not only provide unified storage access abstractions for other languages but also follow naming conventions and development habits that are common in various languages as much as possible to pave the way for quick use.</p>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="powerful-middleware-support">Powerful Middleware Support<a href="https://opendal.apache.org/blog/opendal-access-data-freely/#powerful-middleware-support" class="hash-link" aria-label="Direct link to Powerful Middleware Support" title="Direct link to Powerful Middleware Support" translate="no">​</a></h3>
<p>OpenDAL offers native layer support, enabling users to implement middleware or intercept for all operations.</p>
<ul>
<li class="">Error Retry: OpenDAL supports fine-grained error retry capabilities. In addition to common request retries, it supports breakpoint resumable transmission without having to re-read the entire file.</li>
<li class="">Observability: OpenDAL implements logging,tracing,and metrics support for all operations. Turning on middleware can directly obtain observability capabilities for storage.</li>
<li class="">Concurrency control, flow control, fuzz testing, and more.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="easy-to-use">Easy to Use<a href="https://opendal.apache.org/blog/opendal-access-data-freely/#easy-to-use" class="hash-link" aria-label="Direct link to Easy to Use" title="Direct link to Easy to Use" translate="no">​</a></h3>
<p>OpenDAL's API has been well designed and polished in actual use. The documentation covers everything and is easy to get started with. Here's an example of using Python bindings to access HDFS:</p>
<div class="language-python codeBlockContainer_RtmP theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_Pm3P"><pre tabindex="0" class="prism-code language-python codeBlock_JK9j thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_ODIi"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> opendal</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">op </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> opendal</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Operator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hdfs"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name_node</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"hdfs://192.16.8.10.103"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">read</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"path/to/file"</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="use-cases-of-opendal">Use Cases of OpenDAL<a href="https://opendal.apache.org/blog/opendal-access-data-freely/#use-cases-of-opendal" class="hash-link" aria-label="Direct link to Use Cases of OpenDAL" title="Direct link to Use Cases of OpenDAL" translate="no">​</a></h3>
<p>Currently, OpenDAL is widely used in various scenarios that require cloud-native capabilities, including but not limited to databases, data pipelines, and caches. The main user cases include:</p>
<ul>
<li class=""><a href="https://github.com/datafuselabs/databend/" target="_blank" rel="noopener noreferrer" class="">Databend</a>: A modern Elasticity and Performance cloud data warehouse. Using OpenDAL to read and write persistent data (s3, azblob, gcs, hdfs, etc.) and cache data (fs, redis, rocksdb, moka, etc.).</li>
<li class=""><a href="https://github.com/GreptimeTeam/greptimedb" target="_blank" rel="noopener noreferrer" class="">GreptimeDB</a>: An open-source, cloud-native, distributed time-series database. Using OpenDAL to read and write persistent data (s3, azblob, etc.).</li>
<li class=""><a href="https://github.com/mozilla/sccache/" target="_blank" rel="noopener noreferrer" class="">mozilla/sccache</a>: <code>sccache</code> is <a href="https://github.com/ccache/ccache" target="_blank" rel="noopener noreferrer" class=""><code>ccache</code></a> with cloud storage. Using OpenDAL to read and write cache data (s3 and ghac, etc.).</li>
<li class=""><a href="https://github.com/risingwavelabs/risingwave" target="_blank" rel="noopener noreferrer" class="">RisingWave</a>: A Distributed SQL Database for Stream Processing. Using OpenDAL to read and write persistent data (s3, azblob, hdfs, etc.).</li>
<li class=""><a href="https://github.com/vectordotdev/vector" target="_blank" rel="noopener noreferrer" class="">Vector</a>: A high-performance observability data pipeline. Using OpenDAL to write persistent data (currently mainly using hdfs).</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="future-plans-of-opendal">Future Plans of OpenDAL<a href="https://opendal.apache.org/blog/opendal-access-data-freely/#future-plans-of-opendal" class="hash-link" aria-label="Direct link to Future Plans of OpenDAL" title="Direct link to Future Plans of OpenDAL" translate="no">​</a></h2>
<p>In addition to further meeting the needs of cloud-native data access, OpenDAL will continue to expand user scenarios and actively explore its use in data science and mobile applications. At the same time, OpenDAL will continue to polish its existing implementations and bindings to provide users with a better integration experience.</p>
<p>OpenDAL will also explore how to improve users' workflows in data management and service integration:</p>
<ul>
<li class="">Polish the <code>oli</code> command-line tool to help users manage data painlessly.</li>
<li class="">Implement the <code>oay</code> proxy service to provide users with high-quality compatible APIs.</li>
</ul>
<p>In addition, since OpenDAL is currently a cross-language project, we also plan to write a series of introductory tutorials to help everyone learn OpenDAL from scratch while learning the language.</p>]]></content:encoded>
            <category>announcement</category>
        </item>
        <item>
            <title><![CDATA[Way to Go: OpenDAL successfully entered Apache Incubator]]></title>
            <link>https://opendal.apache.org/blog/opendal-entered-apache-incubator/</link>
            <guid>https://opendal.apache.org/blog/opendal-entered-apache-incubator/</guid>
            <pubDate>Thu, 16 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[On February 27th, 2023, the OpenDAL project achieved a milestone by winning the approval to join the incubator of the Apache Software Foundation (ASF), the world's leading open source software organization. On March 15th, the OpenDAL project was officially transferred to the Apache Software Foundation.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="OpenDAL successfully entered Apache Incubator" src="https://opendal.apache.org/assets/images/opendal-entered-apache-879d5165e27d370849e904ef8d65be25.png" width="1876" height="799" class="img_EjcX"></p>
<p>On February 27th, 2023, the <a href="https://github.com/apache/opendal" target="_blank" rel="noopener noreferrer" class="">OpenDAL</a> project achieved a milestone by winning the approval to join the incubator of the <a href="https://www.apache.org/" target="_blank" rel="noopener noreferrer" class="">Apache Software Foundation</a> (ASF), the world's leading open source software organization. On March 15th, the OpenDAL project was officially transferred to the Apache Software Foundation.</p>
<p>This is a significant moment for <a href="https://github.com/datafuselabs/databend" target="_blank" rel="noopener noreferrer" class="">Databend</a>, as it means that OpenDAL's technology and vision have received wider recognition and support from the open source community.</p>
<blockquote>
<p>The Apache Incubator was established in October 2002 to provide a path for projects and codebases that aspire to become part of the Apache Software Foundation. Incubating projects need to follow ASF's governance and operational practices, and use ASF's infrastructure and resources. Incubating projects need to go through a series of stages and evaluations before they can graduate to become top-level projects (TLPs) of ASF.</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="Apache OpenDAL Project Incubation Status - Apache Incubator" src="https://opendal.apache.org/assets/images/incubator-project-opendal-095982818f2f177cfd4cd267c8f282c4.png" width="1373" height="1006" class="img_EjcX"></p>
<p><em><a href="https://incubator.apache.org/projects/opendal.html" target="_blank" rel="noopener noreferrer" class="">https://incubator.apache.org/projects/opendal.html</a></em></p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="what-is-opendal">What is OpenDAL?<a href="https://opendal.apache.org/blog/opendal-entered-apache-incubator/#what-is-opendal" class="hash-link" aria-label="Direct link to What is OpenDAL?" title="Direct link to What is OpenDAL?" translate="no">​</a></h2>
<p>Data is one of the most important assets in the future, and data access is the key for realizing data value.</p>
<p>There are various kinds of storage services in the market, each with its own unique interfaces and features, which bring a lot of complexity and inconvenience to data access.</p>
<p>OpenDAL provides a unified, simple, efficient, reliable, and observable data access layer that allows developers to seamlessly use different storage services and enjoy the best user experience.</p>
<p><img decoding="async" loading="lazy" alt="M*N to M+N with OpenDAL" src="https://opendal.apache.org/assets/images/opendal-power-549a25c15039d5ff165b082cf2fd7476.png" width="5724" height="1518" class="img_EjcX"></p>
<p>OpenDAL simplifies the process of interfacing different storage services, and provides features such as automatic retry, request optimization, and observability. With OpenDAL, developers can directly access a bunch of storage services, without having to understand and master the details of specific SDKs.</p>
<p>OpenDAL's features include but are not limited to:</p>
<ul>
<li class="">Support for dozens of storage services, including local file system, HDFS, S3, OSS, etc.</li>
<li class="">Provide a unified data access interface, without worrying about the underlying storage details.</li>
<li class="">Support for various common data operations, including <code>read</code>, <code>write</code>, <code>list</code>, etc.</li>
<li class="">Support for automatic retry, request optimization, and observability mechanisms.</li>
<li class="">Zero cost, directly mapped to API calls.</li>
<li class="">Cross-language bindings: Python, Node.js, C (being worked on), etc.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="the-story-about-opendal">The Story about OpenDAL<a href="https://opendal.apache.org/blog/opendal-entered-apache-incubator/#the-story-about-opendal" class="hash-link" aria-label="Direct link to The Story about OpenDAL" title="Direct link to The Story about OpenDAL" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="born-for-universal-data-access">Born for Universal Data Access<a href="https://opendal.apache.org/blog/opendal-entered-apache-incubator/#born-for-universal-data-access" class="hash-link" aria-label="Direct link to Born for Universal Data Access" title="Direct link to Born for Universal Data Access" translate="no">​</a></h3>
<p>OpenDAL originated from the vision of creating a universal, unified and user-friendly data access layer. It came into being in late 2021, initially as a component of the Databend project.</p>
<ul>
<li class="">On December 21, 2021, <a href="http://github.com/Xuanwo" target="_blank" rel="noopener noreferrer" class="">Xuanwo</a> embarked on the design and re-implementation of Databend's storage access layer, <a href="https://github.com/datafuselabs/databend/pull/3575" target="_blank" rel="noopener noreferrer" class="">dal2: Add basic operations of <code>read</code>, <code>write</code>, <code>stat</code>, <code>delete</code></a>.</li>
<li class="">On December 27, 2021, the <a href="https://github.com/datafuselabs/databend/discussions/3662" target="_blank" rel="noopener noreferrer" class="">proposal: Vision of Databend DAL</a> was put forward and discussed. On December 29th, dal2's implementation was integrated into Databend.</li>
<li class="">On February 14th 2022 , dal2 officially separated from Databend's code repository and became a standalone top-level project. It was formally renamed OpenDAL.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="from-one-to-multiple">From One to Multiple<a href="https://opendal.apache.org/blog/opendal-entered-apache-incubator/#from-one-to-multiple" class="hash-link" aria-label="Direct link to From One to Multiple" title="Direct link to From One to Multiple" translate="no">​</a></h3>
<p>Thanks to Xuanwo, <a href="https://github.com/ClSlaid" target="_blank" rel="noopener noreferrer" class="">ClSlaid</a> and many other contributors, OpenDAL quickly became a data access layer that supports mainstream storage services such as AWS S3 / Azure Blob / GCS / HDFS, and provided cross-cloud native storage and access support for Databend's <code>COPY INTO</code>, Stage, Storage.</p>
<p><a href="https://github.com/GreptimeTeam/greptimedb" target="_blank" rel="noopener noreferrer" class="">GreptimeDB</a> was the first large-scale Rust database project to actively use OpenDAL after Databend. Later, with Xuanwo's efforts, <a href="https://github.com/mozilla/sccache" target="_blank" rel="noopener noreferrer" class="">sccache</a> under Mozilla also tried to use OpenDAL to take over the storage layer. In order to provide more comprehensive support, OpenDAL soon added support for GitHub Action Cache.</p>
<p>Then, <a href="https://github.com/risingwavelabs/risingwave" target="_blank" rel="noopener noreferrer" class="">RisingWave</a> and <a href="https://github.com/vectordotdev/vector" target="_blank" rel="noopener noreferrer" class="">Vector</a> were supported as well. The number of OpenDAL users started to grow. More and more users choose OpenDAL as their storage access layer.</p>
<h3 class="anchor anchorTargetStickyNavbar_L3BC" id="skys-the-limit">Sky's the Limit<a href="https://opendal.apache.org/blog/opendal-entered-apache-incubator/#skys-the-limit" class="hash-link" aria-label="Direct link to Sky's the Limit" title="Direct link to Sky's the Limit" translate="no">​</a></h3>
<p>OpenDAL has established a small community and formed a product matrix. In addition to the <a href="https://crates.io/crates/opendal" target="_blank" rel="noopener noreferrer" class="">Rust - opendal</a>, it also provides <a href="https://pypi.org/project/opendal/" target="_blank" rel="noopener noreferrer" class="">Python - opendal</a> and <a href="https://www.npmjs.com/package/opendal" target="_blank" rel="noopener noreferrer" class="">Node.js - opendal</a> bindings.</p>
<p>OpenDAL has released 99 versions since its open source, with 700+ GitHub stars, 349K downloads, and 48 developers. The project has been actively updated. We sincerely thank every contributor for their efforts and dedication.</p>
<p>Being a part of Apache incubator is an important milestone in OpenDAL's development history. We hope to leverage ASF's platform and resources to let OpenDAL focus on providing a neutral, vendor-free, painless, and efficient storage access layer, and better serve the developers.</p>
<p>We expect OpenDAL to be widely used in the following application scenarios:</p>
<ul>
<li class="">Data analysis: OpenDAL can help data analysts quickly read or write data from different storage services, and perform various format conversions and operations.</li>
<li class="">Data science: OpenDAL can help data scientists easily get or save data from different storage services, and perform various preprocessing and postprocessing.</li>
<li class="">Data engineering: OpenDAL can help data engineers efficiently build and manage data pipelines between different storage services, and perform various monitoring and tuning.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="acknowledgements">Acknowledgements<a href="https://opendal.apache.org/blog/opendal-entered-apache-incubator/#acknowledgements" class="hash-link" aria-label="Direct link to Acknowledgements" title="Direct link to Acknowledgements" translate="no">​</a></h2>
<p><strong><em>From Xuanwo</em></strong></p>
<p>Hello everyone, I'm Xuanwo, the Committer of Apache OpenDAL.</p>
<p>The OpenDAL project embodies my personal dream. Now it has entered the Apache incubator with the collaboration of the community. I feel very happy at this moment. Thank you all contributors for your contributions, thank Databend Labs for your support, thank Champion tison for your guidance, thank Mentors ningjiang, wusheng, tedliu and hexiaoqiao for your advice.</p>
<p>Let us follow the guidance of Apache Way to build a community together and create value for users by providing free, painless and efficient data access experience!</p>
<h2 class="anchor anchorTargetStickyNavbar_L3BC" id="join-apache-opendal-community">Join Apache OpenDAL Community<a href="https://opendal.apache.org/blog/opendal-entered-apache-incubator/#join-apache-opendal-community" class="hash-link" aria-label="Direct link to Join Apache OpenDAL Community" title="Direct link to Join Apache OpenDAL Community" translate="no">​</a></h2>
<p>We welcome developers and users who are interested in participating in OpenDAL project to join OpenDAL community and follow OpenDAL's latest news. You can get more information through the following ways:</p>
<ul>
<li class="">Visit OpenDAL official website: <a href="https://opendal.apache.org/" target="_blank" rel="noopener noreferrer" class="">https://opendal.apache.org</a></li>
<li class="">Explore OpenDAL GitHub repository: <a href="https://github.com/apache/opendal" target="_blank" rel="noopener noreferrer" class="">https://github.com/apache/opendal</a></li>
<li class="">Join OpenDAL Discord channel: <a href="https://opendal.apache.org/discord" target="_blank" rel="noopener noreferrer" class="">https://opendal.apache.org/discord</a></li>
<li class="">Subscribe to OpenDAL mailing list: <a href="mailto:dev@opendal.apache.org" target="_blank" rel="noopener noreferrer" class="">dev@opendal.apache.org</a></li>
</ul>]]></content:encoded>
            <category>announcement</category>
        </item>
    </channel>
</rss>