Skip to main content

Inflight Magazine no. 1

Β· 15 min read
Elad Ben-Israel
Matthew Bonig

The first ever issue of the Wing Inflight Magazine.

Welcome to the first ever issue of the Wing Inflight Magazine, our periodic update on what's up (yes, two puns) with the Wing Programming Language, and the community that is starting to gather around the mission to democratize cloud development.

We will try to publish these frequently to keep them short and sweet, but given this is our first issue since the alpha release, there is a bit more ground to cover.

Let us know what you think! πŸ™ We are @winglangio on Twitter, and we hang out 24/7 on Wing Slack.

TL;DR​

Here is a summary of the topics in today's issue:

TS;GMM (too short; give me more)​

The Wingnuts are here​

Before heading to re:Invent in late November we figured that it makes sense to start sharing publicly what we've been working on in the past 6 months. The main goal was to be able to talk to folks at the conference and invite them to check out our very early alpha bits and initial documentation.

We published our manifesto for cloud-oriented programming which describes the background for our project. It talks about the current challenges that developers and companies face when building for the cloud and describes the "impedance mismatch" between the applications we are building and the languages we use.

Since we are in early alpha, we realized that at this stage we are looking for a handful of folks that are enthusiastic and excited about being able to write both infrastructure and code in one language. We definitely didn't expect over a 1,000 people to sign up. We were surprised how many folks at re:Invent have already heard about the project, have already formed strong (sometimes very strong) opinions, and had deep and interesting questions to ask.

We were also thrilled to see pull requests start to pop up with some initial code contributions to the project from @jogold, @yamatatsu, @spara, @rjourdan, @skinny85, @Eitansl, @schosterbarak, @YoniMelki, @perpil, @VictorEB, @joao-zanutto, @tsuf239, @sebbel, @flyingImer, @Warkanlock, @ogre14t, @raywonkari and @hasanaburayyan ❀️ ❀️

This was followed up by a post by Eric Riddoch and another on Hacker News, which brought about 11K new visitors to winglang.io, with even more interesting feedback and relevant conversations:

"This is one of the more sophisticated and cool of the 'Self Provisioning Runtime' concepts that have emerged in the last few years" - zoomzoom

"Why is this a language, not just a framework for JavaScript or whatever? - OJFord

"Great works! Seeing the demo in the front page really makes me think of the cloud architecture as a whole may just be an operating system out of itself." - stevefan1999

"New languages == zero ecosystemβ€”no third-party libraries, community discussion (e.g. StackOverflow), real-world repositories, etc." - MontyCarloHall

"That animation on the home page is sick af" - tomcam

"The team is top notch (of CDK fame) found a non-trivial bug was assigned and fixed in 30 min. In general joy to interact with. Very strong focus on dev. experience. After a very subpar experience of building a very large enterprise project using AWS serverless stack Wing is the first thing that gives me hope that things can be way better." - qaq

We are suckers for open-source communities! We see our team as the seed of this community, and we couldn't have been more excited for all the new folks that joined. We believe that this is how software should be built, and we are here to share our work, listen to your inputs and collaborate on shaping the future of cloud development with anyone who is interested to take part.

Go, Wingnuts πŸš€

Yes, we are still implementing some very basic language features​

In the next few months, our main focus is to implement compiler support for the initial Wing Language Specification. The spec currently includes the minimal set of features we believe are required to build cloud applications with Wing.

We recently added support for while loops (#312) and basic enum declarations (#273).

Wing's while loops look like this, where CONDITION is any boolean expression. In the spirit of minimalism, we decided not to require parenthesis around the loop's condition:

while CONDITION {
// rock!
}

Enums are currently very simplistic (likely too simplistic). They are a custom type and can just contain a list of members (at the moment we don't even support specifying a value for the members):

enum RecordType {
CUSTOMER,
ORDER,
INVOICE
};

let record = RecordType.CUSTOMER;

Naturally enums are going to evolve. There's an interesting discussion over #977 on giving enums Algebraic super-powers, with similar capabilities that exist in Rust and Swift.

Check out the Wing Language Roadmap for an up-to-date status.

Diving deeper into inflight functions​

Inflight functions are likely Wing's most significant language innovation. Since cloud applications are distributed systems and code is executed on multiple machines across various compute platforms, our language needs first-class support for this idea: code that executes in the cloud and interacts with cloud resources around it. This is where inflight functions come into play.

Asynchronous and concurrent programming have been a continuous source for programming language innovation and research. Since the early days of fork() in POSIX, multi-threaded programming, Goroutines, Erlang Processes and the recently popularized, cooperative concurrency with async/await, developers have been looking for ways to write applications that included more than a single thread of execution in a safe and intuitive manner.

Wing's inflight functions can be thought of as a type of asynchronous function that can be packaged and executed on a remote system, such as inside a Kubernetes Pod, AWS Lambda, Azure Functions, on Cloudflare Edge Workers or on any other cloud compute platform.

Our canonic example is a function that wants to put an object inside a bucket:

bring cloud;

let myBucket = new cloud.Bucket();

new cloud.Function(inflight () => {
myBucket.put("hello", "world");
});

The magic happens when the inflight function is referencing myBucket. The cloud.Bucket which is defined (with new) outside the function closure represents a cloud infrastructure resource, not an in-memory object. When the function code interacts with this bucket (calls myBucket.put()), it represents an interaction across machine boundaries. The code is executed inside some compute service such as AWS Lambda, and the bucket is backed by something like Amazon S3. The compiler has to do quite a lot in order to make this a reality on the cloud: it needs to wire up the bucket information during deployment, add the right permissions to the Lambda's IAM policy, and create a code bundle with just the right set of dependencies.

Inflight functions can interact with resources through their inflight interface. This is not very different from e.g. async functions in JavaScript, where it doesn't really make sense to await an async function from synchronous contexts. It is also not very different from how Goroutines can only interact with the world through Channels, or child processes can interact through pipes.

Inflight functions are an isolation boundary enforced by the compiler. This means that there are certain limitations on what can be accessed from an inflight scope. Specifically, you can only access immutable data and interact with cloud resources through their inflight API (like the example above demonstrates). If you try to call myBucket.put() outside of an inflight context the Wing compiler will emit this error:

Cannot call inflight function "myBucket.put" while in preflight phase

Many folks are asking us why is Wing a language and not a library. Inflight functions and resources are a great example. We believe it is impossible to ensure this level of isolation and interaction semantics in existing languages through a library, or even through a compiler extension. We've seen some worthy efforts in projects like Pulumi's Function Serialization, Punchcard and Functionless, and in all of these cases, there are either compromises in safety (e.g. it is possible to capture mutable objects) or in the programming model (e.g. type system is too complex).

We believe inflight functions are a fundamental building block of cloud-oriented programming, and we are on a journey to get them right. From a syntactic perspective, we recently decided to remove the short hand ~> for representing inflight closures, and instead use a simple inflight modifier. We've been debating this for a while, and a comment from a Wingnut, Adam Ruka, tilted the scale in favor of the less quirky syntax. Don't be surprised, though, if ~> will come back, in addition to the inflight keyword, at some point when things mature.

So now, defining inflight functions in Wing is very similar to defining async functions, only that instead of the async modifier, you can use the inflight modifier. Here's an inflight function closure:

let handler = inflight (e: str): str => {
// on air (apologies, the puns are unavoidable, really)
};

The next major step for inflights is to establish a model that allows them to be composed together, while tracking the operations performed by each one for the purpose of permission inference and other wiring. We've implemented the first stage in the SDK (#869), and we are working on implementing this in the compiler (#542), which will enable the creation of resources with inflight methods.

To see what this work will enable, check out this user story which talks about declaring a user-defined resource in Wing with a set of inflight methods. This is going to be fabulous!

Implicit await and explicit defer FTW!​

On a related topic, we decided that awaiting asynchronous calls will be implicit in Wing (spec change, compiler update).

We are trying to optimize the language for the common cases, and we realized that it makes sense to reverse the common syntax around async calls. So, by default, when calling an async method in Wing, the call will be awaited, and you will be able to use defer to access the promise (and await it later).

let handler = inflight () => {
myBucket.put("file1.txt", "1");
myBucket.put("file2.txt", "2");
};

Each call to put() will be awaited by default. Let's say I want to use Promise.all() to await all of the promises in parallel, I can obtain them using defer:

let handler = inflight () => {
let promise1 = defer myBucket.put("file1.txt", "1");
let promise2 = defer myBucket.put("file2.txt", "2");

// hypothetical syntax: see https://github.com/winglang/wing/issues/1004
await promise.all(promise1, promise2);
};

Requesting comments on our SDK specification​

We have been working on the initial revision for the specification of the Wing SDK. This is where we are discussing which resources will be shipped as part of Wing's standard library, what's the right abstraction for each one, how can we map them across the various providers, and cross-cutting design guidelines and programming patterns.

To whet your appetite, here is the list of resources we are considering for our beta. This is just a snapshot from the RFC at the time of this writing to give you a sense of what we are discussing.

ResourcePriorityDescription
BucketP1object storage, similar to AWS S3, Azure Blob Storage, GCP Storage
QueueP1a message queue, similar to AWS SQS, Azure Storage Queues, GCP Pub/Sub
FunctionP1a serverless function, similar to AWS Lambda, Azure Functions, GCP Cloud Functions
TopicP1a pub/sub topic, similar to AWS SNS, Azure Event Grid, GCP Pub/Sub
LoggerP1a log aggregator
TracerP1a distributed tracing system, similar to AWS X-Ray, Azure Application Insights, GCP Stackdriver Trace
CounterP1an atomic counter
ScheduleP1a cron job / scheduled task trigger
WebsiteP1a CDN-backed static website
ApiP1a REST API
MetricP1a metric for monitoring system performance
AlarmP1an alarm that triggers when a metric crosses a threshold
ServiceP1a long-running service, similar to AWS ECS, Azure Container Instances, GCP Cloud Run
TableP2a relational database table
Key-value storeP2a lightweight key-value store, similar to Redis or Memcached
JobP2a long-running compute workload that can be run on demand
WorkflowP2a task orchestration engine, similar to AWS Step Functions, Azure Logic Apps, GCP Workflows
SecretP2a secret value, similar to AWS Secrets Manager, Azure Key Vault, GCP Secret Manager
StreamP2a stream of events, similar to AWS Kinesis, Azure Event Hubs, GCP Pub/Sub and Dataflow
OnDeployP2a variation of Function that runs every time the app is deployed

We would love to get your comments and thoughts on this important pull request, which will be used to prioritize the roadmap for our SDK towards beta.

The std namespace is taking shape​

We are also starting to devise a way for declaring the APIs for the built-in types in Wing. This pull request defines a new SDK namespace called std which is implicitly loaded into the compiler's type checker and will be used to declare and implement the APIs for types such as Array, Map and str.

The first type in std is the duration type which represents a time-based duration (a pretty common thing needed in cloud applications):

let tenHours = 10h;
let twoMinutes = 2m;
let fiveSeconds = 5s;
print("${tenHours.seconds}");
print("${twoMinutes.minutes}");
print("${fiveSeconds.seconds}");

Hot reloading the cloud with Wing Console​

A great example how Wing is able to remove developer experience boilerplate.

Previously, Wing Console needed a .wsim file as input, which is a Wing program compiled for the sim target. This means that if you changed your code, you would need to recompile manually and reload the console.

We've realized we can short circuit the whole experience and simply allow pointing Wing Console directly at a .w source file. The console will take care of watching the file (and host directory) for changes, recompile and reload.

The console now prints compilation errors and clicking on them jumps over to your favorite editor at the right line.

Here's a short video that shows this new feature:

Using Terraform resources in Wing​

The beauty and power of the cloud comes from the endless ecosystem of services that we can leverage as developers to build applications. Contrary to what people might think, Wing is designed with cloud heterogeneity in mind.

In that spirit, we've started to explore what would be the best developer experience in Wing for using any resource from the vast Terraform provider ecosystem.

The following example shows a sketch for what it might be like to define a GitHub repository as part of a Wing application and push a file from a bucket to it. The code uses the github_repository Terraform resource directly from the CDKTF provider.

bring cloud;
bring git;
bring fs;
bring "@cdktf/provider-github" as github;

let filename = "message.txt";
let repo = new github.repository.Repository(
name: "my-repo",
description: "My new github repository",
visibility: "public",
);

let api = cloud.Api();

api.onPut("/messages", (req: cloud.ApiRequest, res: cloud.ApiResponse) => {
let repo = new git.Repository(fs.mkdtemp());
repo.clone(repo.gitCloneUrl, depth: 0);
fs.File.write(fs.Path.join(repo.dir, filename), req.body);
repo.commit("update message", add: true);
repo.push(remote: "origin");
});

NOTE: the fs and git APIs are hypothetical

This issue and this RFC are starting to explore this idea, and we would love your feedback and inputs on this topic.

Summary​

Yes, we know this was a bit lengthy, but we are just so very excited to share what we've been up to. We promise to try and publish these more frequently, so it's easier to keep track.

We are just warming our engines... Stay tuned!

As usual, we couldn't be more excited for anyone to join our journey to make the cloud a better place to build software. We constantly hang out on Slack, and if you haven't already, please join our alpha.

See you in our next flight.