Okay. Let's start with this. Say hi. Hi. Yes. Thank you. Perfect. Tradition, tradition. All right. Welcome, everyone. Thanks so much for having me here. I'm very excited to speak at this conference, to speak here. This is the title of the Zalk Beam Architecture Handbook. We're going to talk about a bunch of design patterns on the Beam. How many of you have used Elixir before or Erlang? How many of you have used it in production? All right. So it's just going to be a bunch of patterns and ideas and tips to work with the Beam applications or Erlang Elixir application on the drone on the Beam.  So this is my username on the internet. I'm a member of the Elixir core team. I've been for three and a half years now. The good news about Elixir now is that when I joined the core team, it was a hipster language. Now I think it's not anymore because Hacker News is saying, would you still pick Elixir in 2019? So probably we've made it, you know, because people are getting tired of us. There's a company called Community, which is a messaging system we are hiring remotely. So if you want to come talk to me later, just come talk to me. I come from a country called Italy. You've probably heard of it. And I think the best thing that we export in Italy is Italian people that are mad at food cooked, Italian food cooked by other countries. So if you want to know more, just follow this Twitter account a collection of screenshots of Italian people that are angry at other people for cooking Italian food wrong, mostly Americans.  For example, obviously there is no spina chicken pasta recipe in Italy.  That's the kind of stuff that they say. A world war won't be enough to forget this. Very strong people. This one very common recipe used in Italy to cause what we call a translation cone of the power that is a huge and uncontrolled vomit explosion. Very graphic people. This is directed to Americans in particular.  Very nice.  Very nice. Lots of vomit references. Then we have a defeated one. I really don't understand why you do this. It's just like defeated. It's a positive person that says, so happy that there is an ocean between us guys. And then my personal favorite one. We're not offended. We're actually vomiting. Very nice. So that's the best thing about Italy, in my opinion, is this Italian people very, very mad at food. Anyways, let's talk about being for a little bit. We will talk about two aspects of this, which are the perspective of a single node. So what happens inside of single nodes? How do processes interact together? And how supervisors work and tips and tricks around that. And then we will move to multiple nodes interacting together. So design patterns and tips to architecture applications with multiple nodes talking to each other. And let's start with from the ground up. So let's start from a single node and a bunch of tips to architecture applications around a single node. And on a single node, the smallest unit of, let's say, life in an airline analytics application is a process. And a process is a unit of isolation and concurrency. That's what it needs to be used for. Just if you need to isolate some operation, isolate failures or isolate resources, then a process is a good idea. If you need to do something in parallel to something else, then a process is a good idea. Otherwise, processes are not a good idea. So an example of where a process makes a lot of sense is if, for example, if you have a TCP acceptor that just accept in TCP connections, and then spawning a process for each TCP connection makes a lot of sense because you're gaining, first of all, concurrency. So every TCP connection can be handled in parallel, but you're also gaining isolation. So that if a TCP connection, for example, goes down, the other are unaffected. So that's a very good use case for using processes. New commerce to the beam often tends to use processes for code organization. Say, like, I need to do this set of operations. I will do it in another process because they belong together. That doesn't make sense. That's what you want to do with a module. You want to put those operations separately in code. Sure. But probably not running a separate process because a separate process entails a bunch of other things. Like, you have a different memory space. You have this running concurrently. So usually the good idea is to put that in a module. And that's why I use a process. When using processes, my recommendation is to never use a spawn directly because there's especially in Elixir. In Erlang it's sometimes necessary, but in Elixir you really have all the tools that you need to never have to use spawn directly. And these tools are things like GenServer, GenServe Machine, Task. So if you need, for example, a process that has state and interacts with other processes, a long-lived process at GenServer is a good idea. If you need a state machine, there's GenSateM. When you need to spawn a task, when you need to spawn a process to do something, Elixir provides this very, very nice abstraction called tasks. And a task is basically a very thin layer around a process that deals with a bunch of other stuff that otherwise you would have to deal with. So let's look at three super quick examples of why tasks are great for these particular things, which are doing an async operation, so something that happens, let's say in the background, doing parallel mapping and parallel processing of collections and doing time box operations. Let's see why this is super useful. In the first example, just doing something in the background, in this example we're just making an HTTP request in the background and we can just do that by spawning a task with task.async and this returns a task data structure. And this is a thin layer around spawn, but it sets up a bunch of stuff that otherwise we have to set up like monitoring and it has a format for the request and response format that you have with this process. So it's very simple. You use it by just calling task async and it returns a task. Then you can do other stuff while the HTTP request is happening in the background. When you're ready to fetch the result of the HTTP request, you can do task await. And task await does, again, a bunch of logic around receiving the response from the task. It will clean up. It will not leak messages from the task. It will just return the result if it's there. Another super good, so this is no using spawn, but it's basically the same thing as doing spawn and then some sending and receiving, just that you don't have to do that and there's less chance of making mistakes. If you want to make, if you want to do some parallel processing and parallel mapping of collections, we have this super cool thing in Elixir called task async stream. So task async stream takes a stream, so any collection basically, and a function and it returns a stream that will process that, will apply that function to every element of the original stream in parallel, but with a bound number of processes. So it will not use all the processes because otherwise if you implement this naively with spawn, you have a 10,000 elements collection, you can spawn 10,000 processes, you have a million elements collection, you will spawn a million processes and that doesn't scale really well. Task async stream will let you use like a fixed number of processes to process the element of the stream as they come. So in this case we're just fetching, say we have a bunch of URLs, we're just saying fetch those URLs and then we're mapping over the response and we can set some options like for example max concurrency 20, like use at most 20 processes. So that's a very nice use case and very simple to use. And the last one is time box operations. So if you want to do something and you want to give it some time, then give up. So for example here we say, we want to make a HP request and we want to give it five seconds and then we want to give up if it doesn't finish in five seconds. So we still start the task async and then we use this task.yield function. This basically says wait for five seconds and if the response is there, get it. If the response is not there yet, just return nil and then we say or. So if it's nil we'll go there to task shutdown and task shutdown will shut down the task but we'll also have nice logic to if there's race conditions to basically get the response while the task is shutting down. We'll go through the code in detail but just to show that there's nice tooling to do. Fairly, I mean not complex but stuff that you have to do if you have to do with spawn takes a little bit of time, takes a little bit of plumbing to set up monitors and the right receives and avoid race conditions and this is much easier to use I think so to avoid spawn. The nice thing about since we're talking about processes messaging between processes is asynchronous. One thing that I really, really like about the beam is that it makes you think in a perspective of distributed systems naturally so in the beam the stuff to be concerned about there's process to process stuff to be concerned about like asynchronous messaging between processes, having timeouts, doing time box operations making sure that you get you send a request and you get back the kind of stuff and then there's a layer on top that is the node to node problems and those are a super set of the problems that you have between processes. We'll go into this in more detail a little bit later but I think it sets up a very, very nice mindset for writing applications. So one thing that I like that you have to think about when working with processes is that you always have to think about a synchronicity so the communication between processes is a synchronous so you have to force yourself to think if I send a request then to know that it arrived I have to receive an acknowledgement but then I have to probably have a timeout but what if the response comes after the timeout this is a very nice thing to focus on because they let you I think build they kind of force you to build more robust systems and crashes as well like any process can crash at any time right and which is the same principle as every node can crash every computer can crash at any time right so you always need to have a plan for when that happens right and the beam forces you to have this plan at a very low level right which I really, really like I really like this quote by Chris Githley saying any of your processes will crash at any given moment and all of their state will be lost which is true it's very hard to it's hard to deal with this right a few things that you can do is for example if you have a process with state it's just to flush the state to a persistent storage and then fetch it back so just keep basically the very latest state in the in the process make the state rebuildable so that if the process crashes it can just start back up and rebuild the state from somewhere or generally just it's important to keep this in mind I think because it makes it force you to build better and more robust applications one thing that's very easy to miss when dealing with this inter process communication and asynchronous communication is the mailbox so Erlang has selective receive meaning that when you receive a message you can pattern match on the message that you receive and some code like this will never fail if it doesn't if you get a message that doesn't match any of the clauses it will just sit in the mailbox of the process so when you have to some code like this you're risking to leave messages in the mailbox of the process that will never be consumed so and that becomes a memory leak basically because you never consume the messages that are there this is rare because it's rare to use receive by itself to use receive manually most of the time you will use something like a gen server which provides this handle info callback to handle messages and the nice thing here is that it forces you to handle all possible messages because if you don't handle one it's actually gonna fail with a function clause error right so it forces you to handle all possible messages eliminating the memory leak of messages not being consumed when we step up from processes the thing that coordinates processes is supervisors right so supervisors are basically this the philosophy is just that you try turning it off and on again so when there's a problem with a process for corrupted state or you arrive at a situation in the process that made it crash there's just another process that restarts it and it turns out like a lot of design this works very well restarting a process from a non-state works well and the process it's common that it's rare that the process ends up in a corrupted state again so a bunch of advice around supervisors the first one is to start with a whiteboard design so I like doing this when I'm designing my supervisors I like to draw them out it's just very practical advice just draw them out because it's very hard to see them in code I think and having components of your system and the parts and designing how you want to handle failures of parts of your system is very nice so you can design the supervision tree and now it reacts to failures on paper I think it's much nicer than doing it in code because it's very hard to read and then another advice is to learn supervision strategies very well and to know when to apply which strategy so we have three strategies one for one one for all and rest for one and they basically one for one means if a child dies only the child is restarted one for all if a child dies all the children are restarted and rest for one if a child dies only the children after it are restarted and this knowing strategies is very powerful I think in combination with knowing how to nest supervisors and nest supervisor is something that's not very advice will not very advertise let's say in the beam community but I think it's a very powerful concept and let's look at a quick example of why say that we have this situation where we have a supervisor and then we have a state process that holds some state and then we have three worker processes and these worker processes need the state to work so then the state process needs to be up what the what's the strategy that you would choose for supervisor for the supervisor on top if we use one for one it works very well for the workers because if a worker goes down one for one just restarts the worker and we're back to the original state the problem with one for one is that if the state goes down the workers are unaffected so they will crash somehow because they can't talk to the state we want a situation where if the state goes down we restart all of the processes so this is not the strategy for us what about one for all one for all is good if the state goes down because if the state goes down we restart everything and we restart in order so start the state first and then the workers will have the state available but if a worker dies we don't really care about restarting the state and all of the workers right so this is not our strategy like if a worker dies yes restarts everything and that's not really a communist strategy for us rest for one is the last one it kind of works better because if the state crashes it will restart all processes after it so it will start all workers which is the right behavior but if a worker crashes it kind of depends where the worker is right if the worker was started as the last worker good that's the only one that's restarted but if the worker for example is the second to last we will restart two workers instead of one which doesn't really make sense for our use case we want to restart only the worker so there's no strategy that will make us happy but if we introduce nesting we can easily solve this problem so say that we turn our supervision tree into something like this where we have the supervisor on top then we have the state and then we have another supervision subtree basically so where we have a worker supervisor and the supervisor is under it once we have this situation it's very easy to make choices for the strategies because we can just say the worker supervisor is one for one so that workers are independent of each other if one goes down and just restarted and the main supervisor is rushed for one meaning that if the workers keep crashing and the workers supervisor will crash but it will not affect the state but if the state goes down the supervisor will shut down and restart the whole worker supervision tree so that's our that's the strategy that we want so it's very nice to be able to nest and composing and nesting supervisor like this makes the strategies extremely flexible to use another couple of bits of very practical advice just supervise every process because every and every process supervised means that processes have proper shutdown if the application is shutting down or if parts of the application are crashing you can trace processes through the supervision tree and they have proper resource semantics so it's nice to have them supervised another very practical thing is just give a name to most of your supervisors because it's very hard when you're in production you're debugging a system to go find the supervisor that you want to find the child process to examine what it's doing if you give name to supervisors it's just much easier it's very practical and then one more thing about supervisors is how to test supervisors this is a topic that's not covered at all or very very rarely in the literature of the Erlang and Elixir communities I think the best thing to do the most practical thing to do is just go into observer and manually kill stuff and see if the supervisor reacts well it's not what we're used to without automated testing and everything but it's hard to test supervisors in an automated way and doing this just gives you a little bit more confidence if you have your application running and you go shut down in an observer you can just right click and kill processes if you do that and you can observe if it behaves correctly it's nice to be able to do that otherwise you can introduce some chaos engineering to test this if you want and if you want to do it more programmatically there's this library called SUPS which is basically property based testing applied to testing supervisors so it will go and shut down random processes and random supervisors in your application supervision tree and if it finds a failure we'll try to reduce that to the minimal case that creates problem in your application so it's a little bit more work it's a little bit more setup but it's nice to if you really want to make sure that your supervision trees that your supervision architecture works moving on to supervisors I want to talk about a pattern that I see implemented a lot in the BIM that it's hard to implement right it's not hard but I think it needs to be discussed in order to be implemented right and that is connection handling so in a lot of applications at least for me it turns out that we have to handle some kind of connection so you have to write for example a connection to a database so you have to write a connection to a message queue or to a cache or whatever you have to write a persistent connection to something that's external of your system so for example it could be redis so you have redis you have your app you have a connection process that holds some kind of connection to redis for example it could be a TCP socket and then you have redis the database sitting there right the problem that I see often is that in the redis connection process people that write code like this they will crash if there's a network fault for example right because the whole let it crash thing like the supervisor will start it anyway so if there's a network fault it will crash the redis connection because the supervisor will restart it the problem is that the supervisor doesn't really provide smart restart logic it just provides dumb restart logic it just restarts it but here when we have these kind of connections we usually want smart restart logic for example we want back off we want to say let's reconnect after one second and then maybe after two seconds so we want exponential back off we want to randomize it a little bit and then one connection and in those cases we I think that the right choice the right abstraction here is a connection manager so connection manager is basically it's still a process that holds a connection but it's a process that is not supposed to crash for things that are very much supposed to happen like the connection going down so if the connection goes down it's a normal case and the connection process doesn't need to go down it needs to relate to say that the connection is down and then it needs to have some logic to say I will try to reconnect maybe in a second and in the meantime when the connection is down it can just return errors so it can represent a lower level of abstraction to the connection that says the connection manager, the process redix in this case is still there if it's connected there's no one zero return error reason and then you basically bubble up the decision of what to do with the error to the application, that's using it for example if you're using redis as a cache you just say if there's an error just fall back to the database and we have now in Erlang a very nice abstraction to help with this which is GenStateM which is an abstraction to build generic state machines but this is pretty straightforward we have basically two states which is connected and disconnected and connected when you successfully establish the connection you end up in the connected state there's a problem with the connection you go back to the disconnected state and simply when you receive a request in the connected state you can't reply so you return an error fun fact, if you look at that connected state you can tell that I can make typos even when running with a pen which I thought was impossible anyways so this is a how to write a process that manages a connection instead of a process that is tied where a connection is a resource of the process that the process just manages instead of being tied to the life of the connection and this also enables one more thing to do with supervisors or not enables but highlights one thing that we need to think about when working with supervisors which is that init is for setting up state so init is basically what a supervisor calls in a GEN server or GEN state machine or any GEN process it will call init and it will wait for init to be done before moving on to starting the next child and so for example if you're writing a connection process it will establish my connection in init the problem is that first of all you're slowing down the startup of your application second of all you're tying the availability of a resource that's going to be unavailable at some point to the life of your application so for example if you have redx in your supervision tree and you want to set up the connection in init you're saying if redx is down in the moment where it starts my application my application won't be able to start that's usually not very good so that's why I'm saying init is just for setting up state so in a connection manager the state is basically just maybe the address of redx where you want to connect to so you just parse options and you build a state that you can connect from and then you return from init and then you connect asynchronously so you basically have an asynchronous init where you connect right after you return from init so the supervisor will have started the children, the child and in gen server for example you can do something like this now you can do continue and then a term when you return from init and it will basically return the supervisor will consider this child has started and then it will just go straight to doing to handle continue which is another callback where you can set up the connection and this also has the advantage of saying of declaring that you can handle for example this dependency in this case redx say being down for your application so your application knows how to deal with redx being down in general what I try to reason about is if I hard need a dependency like for example redx if my application really needs a dependency if it's not there it can't work then you can have something like syncing it where you establish the connection on init you can erase on every error that you get from redx instead of trying to handle it but in most applications I've worked with you don't strictly need these things for the application to work for the application shouldn't go down for example redx is down right in those cases it's very fine to have a synchronous initialization of this connection process plus to handle just errors that come from the connection process when talking about connection process it's easy to go into the discussion of bottleneck processes because if you have a connection process at some point it will not be enough to handle load to that thing for example if you want to talk to redx it's usually not enough to have one one connection to redx you maybe want to have more for the same application otherwise everything is serialized through that connection and that's a general problem with a lecture process not a problem but something to be aware of is that a process is sequential processes are always sequential so if you have a situation like this where you have a cache process and a bunch of processes that want to access this cache if they do a blocking call then the cache will serialize every call so they will every process will be waiting for all calls before it's called in order to get the result because everything is serialized in the cache so in this case sometimes it's easier to do in a situation like this for example you could use a shared resource like ETS where you maybe only have reads go through the ETS and writes still go to the cache so you don't have to care about race conditions too much but in general you can't always do this with something like a shared resource like ETS so what you do to increase your availability of connections to something external to the system is to use or to resources in general is to use pools so a pool is just a connections let's say that are connected to a resource so in the example of Redis the resource is Redis and you want to have a pool of connections that are connected to Redis so that you can pick connections from this pool and have more than one instead of having only one where all requests go through there are two main types of pools in Elixir and I ended up writing a bunch of pools in my Elixir career so I am giving this advice because it happens but the main the two kind of pools that I generally write are either checkout pools or name based pools in checkout pools basically you have the resource and then you have a pool manager which is a process that manages a bunch of connections to the pool and the way it works is that when a process needs a connection it will ask the pool manager to check out the connection and we will use it exclusively for a while and then we will check it back in so in pseudocode it would look something like this where you say connections is called pool.checkout of the pool now the pool belongs to this process and this process is the only one sorry the connection belongs to this process and this process is the only one that can use it then you do something with that connection then you check it back in when you are done so this is very useful when you have resources or connections in the pool that can only be used by one process at once for example you make a request and you wait for the response in one operation when you have connections that themselves can handle like multiplexing for example so they can send and receive responses at the same time which is what DCP does then name based pools are a very very useful thing so name based pools work I ended up writing a bunch of these because they are very useful and the mechanism is simple you basically register a bunch of connections you register them with a name that you can derive so for example just connection underscore and an index and then as long as you know how many you have you can just choose a random index and then you can basically get to the PID of a connection in the pool so this scales better because you don't have to go through a pool manager it also scales better if the connections support multiple processes using them at the same time so they don't need to be exclusive and now in Alixer we also have this thing called registry which helps here because connections can register to this register which is just a name registry where you have a name corresponding to a bunch of PIDs so connections can register to this registry and a registry is basically an ETS table so it's accessible without going through a process so when a client or when a process needs a connection it can just ask the registry what are the connections and just pick one at random and it's nicer because you can do things like if the connection goes down you can de-register it from the registry so you don't get it at all so in Suda code it's you can get all the connections from the registry there you can choose a random one and now you have the PID of the connection that you can use so when you have connections that don't need to be exclusive this is a very very useful kind of pool talking about going back a little bit to error handling this is a topic that's very sensitive on the BIM and it's very sensitive with supervision and connection managers and all kinds of things my advice is to handle all expected errors so for example this connection TCP disconnection is an expected error and that's something that you probably should most of the time handle let it crash is a very in my opinion misunderstood phrase in the BIM especially for newcomers because we try to settle it as you can write programs that crash at any time and everything is going to be fine that's not really the case because if you have expected situations like a TCP error and you crash you're not going to have a good time you're going to have a good time if you crash an unexpected or unrecoverable things so for example if you have something that you parse when it comes into your system and you say from now on it's an integer then you don't have to check that it's an integer every time if it's just do stuff and if it's not an integer it will crash that's like an unrecoverable state because it will take probably more time to try and reparse it or find out where it went wrong usually crashing is good in those cases because the system won't go down like supervisors still provide a protection for the system to go down from the system going down so that's very nice but crashing on expected errors doesn't really work because supervisors are for emergency restarts so they don't have smart logic to do restarts as we were as we were saying in the connection manager example if you want to do back off you can't do it through supervisors supervisors just something crashes restarts restart it, something crashes again restart it at some point just crash the whole part of the tree and then bubble that up it's not smart logic so if you need smart logic you just need to implement that in process supervisors just for emergency restarts so it's something crashes and it's unrecoverable a supervisor will guarantee that your whole application doesn't go down but the failure is very localized to a little part of the supervision tree and it takes a while to bubble up and there's a chance that it doesn't stay so those are a bunch of tips and tricks on processes and supervisors and everything is on a single beam node but many times you have applications that are main of multiple beam nodes I tend to reason more about applications that are on multiple nodes but that are not communicating through distributor even if it's mostly the same thing but this let's say that this means applications are run on different nodes but don't communicate to each other with distributor Erlang so there are normal services communicating to each other or even just distributor Erlang so multiple VMs actually connected together and communicating to each other, the same principles apply the nice thing that I like about Erlang is that it forces you to think even when you're a process to process communication but you have to think about when you have node-to-node communication basically node-to-node communication is the same problems as inter-process communication so you have async delivery you have crashes unexpected crashes plus unreliable message delivery so when you have process-to-process communication you have one advantage and that is that if you send a message to another process it's guaranteed to be delivered to the process it's guaranteed to not get lost unless the system crashes but then you have other problems but if the process that sends and the process that gets it are alive it's guaranteed that it will get to the process this is not true in distributed system because if you can send a message to another process and the message can get lost if the connection gets interrupted so you have a little bit more problems but the base set of problems is the same when you have node-to-node communication when you have distributed systems with multiple nodes when you need each other I want you to know that BIM doesn't solve distributed systems this is not true BIM solves distributed systems this is my reaction BIM solves distributed systems no BIM doesn't really do anything for distributed systems except to provide a good set of tools so the tools that BIM provides make it easier to deal with a bunch of distributed systems problems but doesn't provide any solutions let's say it just provides tools a few examples of tools that I really like are like send so send is very simple it lets you send a message to a process the cool thing about send is that it works from node-to-node so if you have distributed early you can send a message to a process that's leaving on another node and you don't have to care you can do it transparently or kind of force to write your interaction in a synchronous way so you have to if you want to know if the other process got it and processed it you still have to wait for an act and everything it's very nice because you can use send basically in the same way you can use the same semantics and the same handling when you use send if you're sending a message to a local process or to a process on another node and same thing goes for things like process monitor node-to-node monitor if a node or if a process whether it's on this node or another node goes down those tools work very smoothly or global process registration is like a global registry name registry for processes these are tools that make it very cool to work with distributed systems and with distributed applications but they don't solve the inherent problems like how do I know that the other node got my message right one thing that we talk about that I want to really quickly touch on is hot code upgrades in the beam so I've never done hot code upgrades in the beam have you ever done hot code upgrades I don't even need to ask because you haven't because nobody has it's just one of those features it's cool that it's there where you can update code on the fly without shutting down your application but there are a bunch of enemies to this right now in the modern development world it's the same number one right if you have docker you really have a hard time because when you're building another docker image with updated code it's not straightforward to update the code on the fly in a running system so usually it's just easier to stop the container and start a new one but my question is do you even need hot code upgrades and my answer to myself is probably not so if you have a case like this where you have for example a server and you have a web socket client and this is a good use case where you don't want to interrupt the connection the web socket connection when you're pushing new code to the server you don't want to interrupt that the problem is that in the world that we live in connections suck so the connection will be interrupted anyways for a million reasons because people put phones in airplane mode because signal goes away because the connection is unstable whatever reason the connections are terrible so you still have to handle the connection going down might as well just make the deploy where you shut down an application and start again just a particular case of like one case possible case of why the connection goes down right and one more thing I want to talk about is to be more not to beam so when do we use the beam and when do we use other solutions for example if we want to talk about data storage when do you use postgres and when do you use something like reac so in beam solution same goes for key value storage when you use retis and when you use ETS or Nija I tend to go for whatever is best for the case right of course so if I need something quick and something fast or something that's fine on a single node for example for key value storage ETS is very very good because it's super fast and you don't have to have the overhead of connections and the protocol and everything but you have to think about a bunch of things like interoperability so are you writing all your services in Erlang because if you aren't then having a database that's not proprietary to the beam might be very nice because you can access it from multiple services does your database need relational features like foreign keys and stuff like that then it's very nice to have a proper relational database right do you need to do data analysis on your data like it's harder to do data analysis on ETS than it is to do data analysis on retis because retis provides a bunch of tools people wrote tools that work with retis and some of the replication is very hard like postgres will handle that for you retis will handle that for you but if you have to build replication on top of ETS it's not going to be fun right so my advice is just use the right tool for the job here and then I want to talk about one thing that's very very dear to me that I kind of like hinted at throughout the whole talk which is intercomponent communication that could be inter-process communication inter-node communication just like how do two things talk to each other asynchronously right and it boils down really to requests so when I have an elixir process or an Erlon process and that process sends a message to another process it's a request you can call it a request right it's just telling the other process to do something and so it could be for example an htp connection process that asks the database connection process to make a query and get results right this is the same exact same thing in a distributed systems where you have for example multiple services right you can have one service like order service just send a request to the storage service and I think it's really key when writing applications to understand what kind of request you're making between your components in order to write good applications right and there really are three kinds of requests there are at most one request a list one's request and exactly one's request and categorizing your requests not all requests but categorizing when you're dealing with a particular request putting it into one of these categories helps a lot at least helps me to decide the behavior that is right for this right and to put the right mindset for dealing with this so let's quickly go over all three and most one's requests are basically just black hole behavior so you're just sending a request to somewhere and you don't care if it gets processed you only care that it doesn't get processed twice but if you send it once it will not get processed twice right so for example this could be this is a gen server cast so I'm just sending a message and I don't care for the response in a service to service to communication it could be a message that you put on RobinNQ once and you don't care if it gets there or not and this is very useful for very shuggy attitude right and it's very useful for things like for example push notifications for messages like when I want to send a push notification it's usually better to send it and most ones because if you send it if you don't send it maybe the user doesn't notice if you send it twice the user definitely notices right so it's a good use case for just trying your best like best effort just try to send it once sometimes you want to make sure that your request is processed at least once so this requires a little bit more state because you need to keep track of whether you get an acknowledgement from the other component that the request was processed so for example in this case you just say I have a component I make a request does it get act no I retry does it get act yes then I'm good that's squares for good I don't know why so a trick for like a fundamental component of this of at least once request is the retry so when you want to make sure that something gets processed you need to implement retry strategies so that if it fails you retry to do it and the trick on the receiving side with for at least once request is idempotence so idempotence means that you can consume this you can say handle the same requests multiple times without being with the same effect of handling it once right so for example this can be I don't know it delete on the database it doesn't matter if you delete something once or if you delete something 100 times it's still going to be deleted at the end right and when you have idempotence it's easy because then you don't need to care about making sure that the request only gets to the recipient once you can just get there many times and then it just processes many times and it's the same thing and then the third kind is exactly once request those are the most expensive ones exactly once means that you want them to happen only once right and they require states at both the sender and the recipient because the sender needs to keep track of whether the recipient act this request so he needs to retry, needs to keep a state for that and the recipient needs to keep to ensure that the same request if it ever gets the same request for some reason for example a retry that was spurred from a retry connection so you get the request twice because the sender thought that you didn't act it so you need to ensure that those multiple requests multiple copies of the same request are only processed once so for example you need to give request an id and you need to have to ensure that when your process request is not already been processed you need to store the IDs of the processed requests and this is very rare that you need this so if you can try to reason about your system without this it's easier but it's necessary sometimes for example for financial transactions where you want to actually do the thing only once the transaction only once so conclusion about this main advice, use the right tool for the job very obvious I think that right now we live in a very polyglot software development world so I really like the beam but I think that you should always consider if it's the best choice if you want to introduce other components in your system you need to be sure that you're not locking in to the beam too much so go use Redis, go use Postgres if they make sense and if they let you use other services and then the other main advice is generally learn about distributed systems because distributed systems the problem is that distributed systems try to solve our problems that we deal with all the time when you have systems in multiple services talking to each other multiple nodes talking to each other it's a similar set of problems and then one advice is that beam architecture is good so take it with you even if you don't write elixir so things like this kind of reasoning about requests things about asynchronous communication about restarting processes that crash so having some kind of isolation those are I think generally good things so if you can take them with you even if you're writing something else that's very good a few resources the first one is designing for scalability there's a book to read the second one is the fred.ca is the blog for fredhabbert which is a very very nice guy that writes very interesting things about the beam that I really like reading and the third one is a book about distributed systems for fun and profit it's just a book about introduction to distributed systems that I recommend everyone reads if you're writing systems where you have multiple things interacting with each other you


Hello everyone this is Ashley here from Ecosystem Restoration Camps and this is the update for February 2020. So keeping with the theme of making these video updates each month I am going to be telling you about what has been happening in the movement and getting you excited for what's happened and what's to come. So since we last did a video we have now partnered with 23 projects that have become camps. If you look on our camp map on our website page on our home page you'll see all of the camps and where they're located and the camp pages are being added as we go so check them out some really cool projects happening there. We have also been invited to take part in a consultation with the UN about the decade for ecosystem restoration and to input into their strategy which is really exciting. The Camps, Camp Villa Organica in Mexico and Camp Mundo Nuevo in Colombia have finished their latest experiences and they've done some really cool things. Camp Villa Organica have been removing invasive species from existing trees they've been planting mesquite and agave which are two pioneer species that grow really well in arid conditions which is also a part of the agave project that Regeneration International is doing that involves regenerative agroforestry with agave so you can make regenerative mescal which is really cool. We have a blog post about that on our website if you want to read more it's a really cool idea. They have been learning how to make different types of compost they have been learning about how to grow food regeneratively and just generally doing a lot of lovely sightseeing and getting to know Mexican culture more and then Mundo Nuevo in Colombia they have the campers have been creating a tree nursery by going into the surrounding tropical forest and taking seeds to plant into a nursery they will then grow the trees and plant them out in the patches of land that have been degraded by cattle farming. Those areas are now covered in something called elephant grass which is an invasive which they've been removing and they've also been creating swales to make sure the water doesn't run off. So that's also really great and the camp has had a really great time and both camps will be planning another camp in the next few months so watch out for the website to see the new dates if you're interested in going to one of those. Camp Via Soleil in France is one of our new camps and they have planned a camp in April from the 18th to the 24th of April. The schedule in the handbook is being created at the moment so if you're interested register your interest on the interest form on the Camp Via Soleil webpage on our website and we'll send you the handbook and schedule when they're ready and that will give you an idea of the activities but I can tell you what the activities are going to be now. They're going to be learning how to create a Johnson's Sue bio digester which is a really effective form composting. You're going to learn how to create biochar and what biochar is used for and all its benefits. You're going to be learning about water retention, creating some water retention structures. You're going to be creating pollinator habitats and then there is some natural building involved as well with the natural buildings on the site that need to be restored and then some really fun activities like canoeing down the river and local wine tasting.  We also had a lot of amazing media coverage over the last month and a half. We had a video released by Business Insider which is really amazing. That's featured our work and sent out to a large audience. We have been featured on the Green Dreamer podcast so if you type in my name Ashley Brown into the Green Dreamer podcast you can learn a lot more about our work during that interview as well. It's really fun to do and then the ecologist has also published an article about our camp in Mexico so we've had a lot of great media coverage recently which is really exciting and we've also been working really hard on our online course which is set to be launched on the 15th of March. So again keep your eyes peeled for news about that. So yeah very busy time. I'm going to keep this video short because shorter is easier and more digestible but I hope you enjoyed this update and we're really excited that you're excited about Ecosystem Restoration camps. Until next time, bye.


Thanks. Thanks, everyone. So this is resources squared, or otherwise, and hopefully, resources on resources, what I believe to be a core primitive when it comes to reactivity. And that doesn't mean just forever, but first, a quick introduction of myself. Online, you can find me everywhere at nullvoxpopuli, and at the bottom here are some links to projects and just where you can find me. So this presentation will have a lot of links, and it's written to still be useful and have all the context when it's uploaded and read. However, when live links aren't very helpful, so almost all links will be represented by QR codes, and most of what I'll be linking to is documentation and live demos. Now QR codes can get a little squirrely. So I did test this, so it might work, but if you're in the back of the room and you want to be distracted while I'm talking, feel free to move closer so you can scan the QR codes. And if you're online, make sure to get your phone out. I like doing things while I'm doing things, so QR codes are good stuff. I'll also upload the slides to GitHub afterwards. All right. So you didn't get to see that, or this, or the video, all right, yeah, look at the QR codes. Oh, man. Okay. All right. So here's a list of things I've done over the past couple of decades, TLDR, I've done a lot of things, and I've used a fair number of technologies, and I've been using Ember the longest so far, chat GPT most recently. So on the left is a picture of my partner and favorite human. She is the best. Outside of programming, I like swing dancing and video games, and this is a screenshot from Beat Saber, a virtual reality game. So I have some disclaimers. I'm going to try to get through these real quick, but some may consider parts of this talk experimental, and that's okay. There are certainly gaps today. We need more learning materials around resources, patterns, in and outside of Ember. We need to actually implement StarBeam for Ember, and for those that only stick to what is in the official documentation, this may feel experimental and out of reach. However, to help mitigate that feeling, I've been working on some learning materials and tutorials. I'll be working to help close those gaps, and I'll try to answer anyone's questions and provide help. Wherever you think you need help, I want to try to be that for you. The goal here is to solve real problems more efficiently while also reducing cognitive load on everyone writing their Ember apps. All examples are going to use the new GGS format. Thankfully, we had a talk on this yesterday on this new format, but here's a quick TLDR, maybe recap, for converting between the old and new in your head. Whenever you see a template block by itself, that is most similar to a template-only component. The key thing here is that it's always a component, and you always know where things are defined. Whenever you see a template block within a class body, that's equivalent to a glimmer component with a class, normally two separate files. The idea is that it does not make sense for templates to be a separate concept. Both examples are full-blown components. It's only a matter of if the component has its own state. All of this is my opinion, but I'm committed to these opinions, and it's not to say that these opinions are not shared by others, but I genuinely believe that they make not only our ecosystem stronger and better, but the concepts benefit all ecosystems outside of Ember as well. There's no RFCs for what you're about to see for becoming part of the default blueprint. However, I do plan to bring these concepts to the default experience, and I'm starting an RFC when I get home. Okay, last disclaimer, I promise, it's extremely important that there are easy migration paths within the community. Programming is hard, and some migration paths are not and have not been so easy. The overall goal for everything I'm working on for and around this talk, resources, et cetera, is to be a polyfill for Starbeam. Ultimately, I want Starbeam to be the resource implementation we use. But in this talk, I demonstrate with the library Ember Resources, because you can install and use it today. At the moment, I haven't written any code mods, because there are still some designed details to work out with Starbeam, but any behavioral difference between my library Ember Resources and Starbeam should be considered a bug. I am committing on keeping support for Embersource 328 for as long as I can. I know a good number of folks were caught off guard by the number of deprecations that came up during the V3 series. I think I heard there were like 70 deprecations or something. That's a lot. So I want to make sure that folks who are still on V3 can use the patterns coming in the future. So getting back to it. With the introduction of Ember's first edition, Octane, a new reactivity system was introduced. Tracked properties. By the end of the 3x series and leading up to V4, we had two user-facing reactive primitives. At tract and functions. In Ember Octane, it was assumed that all reactive state or root state, the very root of what auto-tracking pulled on, would exist on a property and a class, which would then be decorated with the at-tracked decorator. This use of a decorator allows for a hidden getter and setter so that the reactivity system can still operate while allowing native access to those properties. We'll see how this works later. So in Ember Octane and before, functions were called helpers. It wasn't until Ember Source at 4.5 that plain functions became supported as a reactive primitive without the polyfill. However, helpers, now called classic helpers, had two implementations. A simpler function-based version and a class-based version. These both required framework-specific abstractions to use and build. But the class-based version of these classic helpers had clean-up capabilities, though awkwardly via inheritance. So what about modifiers or components? We'll come back to these later, and yesterday you may have seen something in the keynotes that may allude to what is coming. For components, though, I'm going to propose that there are not primitives at all. But first, I'd like to propose that we as a community rethink reactivity in general. Instead of at-tracked, let's think of and redefine these as values, making the at-tracked decorator a user of reactive values. A value is the most basic kind of reactive primitive we could possibly have. These can exist within functions, outside classes, anywhere. And this will be a theme throughout this new way of rethinking reactivity. For function-based helpers, we can just use plain JavaScript functions. Supporting plain JavaScript functions as a reactive primitive, as well as their arguments, is essential for reducing the number of abstractions folks need to learn when they learn number. For class-based helpers, we can use this new primitive functions with lifetime and cleanup. This allows us to compose our value primitives for managing state throughout the lifetime of the parent object. And then we can have optional cleanup. We'll expand on both of these concepts momentarily. For a couple of these, though, we still need abstractions because reactivity is not built into the browser. We'll call values cells, and cells provide the abstraction with which we can build at-tracked, and allow us to use reactive values everywhere, not just classes. Functions we can leave as is. They can directly access the state on cells. These will auto-track and are completely transparent to the renderer, just like getters within classes. Functions with lifetime and cleanup are resources. These are the key abstractions that we'll focus on for almost the rest of this talk. All right, a few slides ago, we hand-waved over the fact that at-tracked extracts a secret value. Here are the secrets behind the hand-wave. The secret value can be thought of as a cell. All right, so what is a resource? It is a unification of a lot of concepts. In Ember, they rationalize class-based helpers, modifiers, services, and routing. Outside Ember, they rationalize hooks and eliminate the need for effects or help eliminate the need for effects. They allow you to derive data in ways that previously would need effect-like behavior. A resource's reactive function yet represents a value. It is bound to a lifetime and may have cleanup. So what does a resource look like? This is what they look like when using Ember resources, which you can install today, all the way back to Ember 328. You can do this. For this particular resource, we create a value, a cell. This represents the current date time. We can set up an interval and clean up the interval when the resource is cleaned up by whatever the parent context may be. In this case, it is a small component. Lastly, the time is returned. The renderer inherently knows how to render cells as their values. Looking at the code snippet on the slide here, this is the star beam version. The only thing that changes is the import. So this is the anatomy or layout of a resource. You set up initial state, provide optional cleanup, and then return the value. We can configure arguments, and this is probably one of the bigger differences between Ember resources and star beam. Due to how Ember's plain function invocation works, we need a wrapper function to handle receiving arguments. This is because Ember doesn't have a public API for tweaking how plain functions are invoked from templates. It is intended to just be a function, though, and making it just work will be the process of implementing star beam. There's nothing magic going on here that a user of this would need to be concerned about. When resources land natively in Ember, this wrapping resource factory won't be needed. So cleanup is useful for cleaning up event listeners, canceling observers, timers, disconnecting from web sockets, maybe freeing up memory. Bunch of things we could clean up. So far, we've been looking at a clock example where the interval needs to be cleaned up. Let's take a look at another situation which may need cleanup. Now, cleanup in general is a concept we're likely used to. Components, modifiers, and class-based helpers all have a will destroy method. If you're the type of person who likes using features as they're released into the framework, you may have seen at Ember destroyable. Cleanup is co-located with setup. This is an improvement, but we can do better. So resources have more ergonomic cleanup. It is co-located with the behavior, which is a goal that will destroy methods didn't know to care about yet. And there are no additional imports, which leads to better intelligence and editor assistance around this API. So resources have a lifetime. What's a lifetime? An application has a lifetime. It has a start and an end. And during testing, oftentimes, you have one application lifetime per test. It may even be a stripped down lifetime, only what's needed for rendering a component. But you could visit a route during the lifetime of your application. That route could be thought of having its own lifetime as would the components rendered within that route. This precursors all the way down the rendering tree. Along and within that rendering tree, we may have a resource or it could be a component that fetches data for this route. And when the parent lifetime ends, so do its descendants. Now, when working within the framework, we need to hook into the application owner for access to services and set up the destroyable relationships to the appropriate lifetime. If you've ever done this yourself, it is a lot of work. So here's what the code looks like if you wanted to link up to a custom class, to a component, so that then gets the owner and has this destroyable method called when the component is torn down. We have that cached, we have set owner and get owner, we have associate destroyable child. We don't want to do any of this. This is a lot of boilerplate. Resources do this for us. When we use a resource, it automatically has an owner. We get linked template invocation for free and it automatically has the correct destroyable association regardless of where it's used. So when it's used in a template block component or within another resource or service and that parent template block component resource or service is destroyed, so will that resource be also destroyed? So resources can easily be composed together. They abstract away the details and inner workings of the framework that would otherwise be exposed to your apps. Using our resource that represents the current time now, we can define a new resource formatted now. We can compose now via the use function and it renders in a component the exact same way. Okay, great, but why does any of this matter? Resources allow us to implement concepts that we are familiar with, but with greater ergonomics. They allow us to define how data or state is derived with the flexibility of optional cleanup. This represents values. We've seen the clock example where the value is the current time. We can manage the lifetime of modifiers, services, routes, and not only do resources allow us to implement all these concepts in a coherent and concise way, rationalizing all these different things together. They allow us to bring our reactive concept to the broader JavaScript ecosystem, which is the goal of StarBeam. So let's start with examples of resources as values. And before diving into this example, I'm sure the first thing you noticed was the static on the right. And if you're wanting to scan the QR code, it redirects you to a REPL or a playground where you can start poking around this and try to find bugs to call me out on the code that you see. But yeah, let's see. So this is representing a clock just like before, but implemented the old way. It has a number of problems. Our time value is bound to a component, so we can't tear down our interval at any granularity smaller than a component. I'm sure you all have seen components that do too much. And this pattern adds to that. The tear down and set up are disjoint. There is a life cycle hook you have to know about since components lend themselves to be overburdened with responsibility. It's very easy to intermingle different behaviors, clean up and set up all over the place within a component. And here we've hacked in a life cycle event via a set once property. The getter is still reevaluated every time underscore time changes. And if we were to add tracked data into here, we're at potentially a high risk for a memory leak. So here we can already see that this looks way less complicated. Set up and tear down at the interval I co-located, the entire construct is focused on a single responsibility. Tear down occurs at the curly brace level where time is used rather than at the component level. The lifetime for this resource is the curlies. And lastly, if we don't need a bespoke life cycle via set once property. And here is that code rendered. On the right here, you can see that time is progressing slowly, I hope. So now let's compose this interval like we saw on a couple slides ago. So here we compose using the use utility given to us by the resource and format the current value of the time resource. I've set up an argument receiving function so that we can see how to use this composition to make it more reusable, yet configurable atomic concepts. And here is what that looks like. At the top here is the original time providing resource and then we can compose it just underneath. This is using the intildate time format built in utility and then just rendering the current time in four different locales. So in this example, let's say we want to know the most recent person to have visited Tatooine, a desert planet in Star Wars franchise. We can assume that the method of retrieving that information exists and that the implementation might look a little something like this. This isn't a lot of code, but it does require scrolling. So we set up a socket and subscribe to messages. Then we define how we want to format the last message. And then handle cleanup. And like with the other demos, there's a common theme of responsibility leakage. With components, it's very easy to accidentally make a component responsible for more than one thing. And what we want is single responsibility concepts that represent the value, which in this case is the most recent person to visit Tatooine. So when using a resource, we have much easier time managing socket information. Cleanup is straightforward and co-located. We can manage state in encapsulated fashion and we can define a sort of getter for formatting the output. This QR code's a little bonkers. So the output looks like this and is it updating. There it goes. Okay, this is using the Star Wars API because it's free, it's pretty good. Okay, here same as before, we have a long file and it's quite a bit of code. Let's see what all it does. We're trying to handle loading state, error state, reactivity. We want to have a stable reference to the state so at cash is needed. We also need to handle cleanup and the combination of a board controller plus we'll destroy, but also reactive cleanup as the URL argument changes. Kinda looks goofy. So when using resources, we can co-locate and focus on a single responsibility. This code doesn't scroll and we can handle all of the capabilities that we mentioned on the previous slide. Loading state, error state, reactively responding to URL changes and canceling the request when we no longer need it. So here's what that looks like. Let's see, there's a bit of extra code in here. If you go visit this, I couldn't make it a QR code because the URL was too long but browsers are fine with that amount of URL length. But I'm scrolling through the code just to prove it's not smoke and mirrors. So what's super cool about using resources to manage data fetching is that you can compose them just like we did with the current time and you still get individual reactivity per resource. So here we configure remote data on three different endpoints. Note here that this uses an example you till from Ember resources, remote data. Fear not though, Ember resources is a V2 add-on so if you don't import it, you don't pay for the bytes. Now when rendered, it looks like this. On the right, you can see that each request for people, planets, and starships takes its own amount of time to load and it just so happens that the Star Wars API only returns 10 records at a time. This is as fine grained or as combined as you need. Some UX patterns may want fewer loading indicators than what you see here. So in Ember, there are a couple places to load components, in routes and not in routes. Loading data outside of routes is immensely useful and you'd otherwise be forced to drill props through countless layers of components. Some folks imperatively manage data as properties on a service, updated from routes, but this is troublesome due to how error-prone unencapsulated behaviors are. A common thing developers reach for and something resources make easier is fetching data within components. However, if not properly managed, this could lead to the N plus one data loading problem where you render a list, that list renders a component where each item within that list yet makes another request. Today, this could be mitigated by making the implementation of some data fetching resource. Use a backing service to manage a shared cache between the resources and then batch those requests together to minimize the number of requests. In today's keynote on Ember data, we saw that Ember data's request manager can be that cache. There will be demos of this in the near future. And in yesterday's keynote, we saw that resources will soon power the next generation of route loading behavior and mitigate waterfall data fetching, which is very exciting. We've seen that resources can be wrapped in functions to reactively handle arguments and we can extend that to modifiers. This is supported in Ember resources as of this morning and here we are doing a little animation effect on an element. The important thing is that this resource is the same as any other resource. It's the same API. It's only wrapped in a function that receives an element. And then whatever args you pass to the modifier and this is what the animation looks like. So now for those worried about bundle size, fear not, Ember resources is a V2 add-on. So if you don't import it, you don't pay for the bytes. All right, so we know that resources are bound to a lifetime and that applications have a lifetime. This means if we install resources on an application, the resource effectively acts as a service. We can define a resource that has some state. For brevity, the state will be a number, but it could be any service you can think of. With this resource, we can return a getter to get the current value, as well as a method to increment that value. But this could just as easily be an instance of a class. We can then create a component which then uses the counter resource here. This decorator is what does the linking between the resource and the overall application. To demonstrate that state is actually a service, I've rendered the component three times here and here is what it looks like in action. You can see that all the buttons share the same state. So can a resource also be a component? Well, kind of. If you like React, it may look like this. Returning a template only or presentation or stateless component as their value. Using the closed over function within the resource as the state. However, the main thing is that every framework already has really legit component implementations and those implementations are really good at what they do. But we can do it too. You can see, however, that at the bottom of the code snippet, in order to get this to work, you have to invoke the resource like a function and then render its return value. But this is only a component manager implementation away from actually working as a component. And it really shows how useful the template syntax is. I mean, this wouldn't be possible at all with the classic two file syntax. This is one of my favorite quotes about doing goofy things. But science is pretty fun, so let's keep going. So here's what the demo looks like. You can see that today the resource still needs to be invoked like a function and if we only invoke it once, each time we render the component, the return, each time we render the component return from the resource, they share the same state. I don't know if this has any use cases, but an important thing to note is that the function returns a component. So we could adapt this to a component manager and have the invocation happen automatically, but I just don't know if it's worth it. But if people really want it, I guess I'll make it. So let me know. So I mentioned this a while back and I want to revisit this idea. Components are not primitives. So recapping what the primitives are, we know that from Ember octane and now that we've renamed some of the primitives that octane introduced, we have values, functions, and now resources, which represent the value bound to a lifetime and rationalize class-based helpers, modifiers, and services. And these can all be authored and shared anywhere. And that's the main goal of Starbeam. We can write our application logic once, whether that's data fetching, UILogic, modifiers, anything reactive and just use it. And it's not only for Ember, but React, Preact, View, it's Felt, anything you want to use. It's super exciting because most other frameworks don't have modifiers. And as far as I know, none of them have resources. So components wrap the primitives. Components are refactoring boundaries. They are containers for organizing higher-level concepts. And the word resources may be a bit overloaded depending on your background. I don't know if anyone saw in the Discord chat yesterday, but there was some goofy wordplay happening. Yeah. So there's this other thing. If you pay attention to TC39, resources are also a concept in JavaScript itself. The proposal is stage three or in the implementation phase. The JavaScript resources have a similar purpose. They provide a means to manage the lifetime of an object. Ember and Starbeam resources provide reactive implementations of this concept. And it may make sense for the implementations to build on top of JavaScript resources once they are shipped.  Okay, so what's left? Mainly, I need to do more work on Starbeam itself. I need to get it into Glimmer. I need to write some code mods for folks using Ember resources to get them over to Starbeam when that's a possibility. And I need to put up some RFCs because I mean, at least I think that the whole way we're thinking about reactivity has become a real cohesive story and is quite a bit more buttoned up since Octane's release. So in much the same way that promises are better than callbacks, resources are better than effects or other ways of working with lifetimes. Some last thoughts I leave with you before the end here is derived data is really good. Resources help you model any situation as derived data and resources are not effects. Someone has to pull on the resource for it to begin executing. And resources are part of a plan to bring Ember's reactivity to everyone through Starbeam. And you can install this right now and get started before I walk off stage. So if you wanna use the live editor or REPL Playground I made, it's here on the right. The left is a tutorial which includes resources as well as GJS. And it teaches other concepts that I think are really important for people to know writing Ember applications in 2023. So thanks for listening. And as always, you can ask me anything at Melvox Popular. Thank you.


Welcome to The Pyramid Insider, I'm Tyler Patner and today we are going to be going in depth on the Umarex Gauntlet II in .22 caliber. Now the Gauntlet II was announced right around just before summer of 2021 and obviously is the successor to the ever popular Gauntlet. It has a lot to live up to and Umarex has done a pretty good job of enhancing the original Gauntlet to give you quite a bit more power and also add in some other very much needed features that a lot of you guys asked for with the original Gauntlet. I think the best way to compare though and talk about some of these upgrades and enhancements is to pull out an original Gauntlet. So I have that here. Now looking at the original Gauntlet compared to the Gauntlet II, you have some striking difference obviously in the looks of the stock. The stock is Umarex's tactical precision stock and it has a lot of nice enhancements over this original Gauntlet. One stock, the biggest one being a lot thinner, a lot easier in the hand, not as bulky answering a lot of the calls from folks out there that just didn't seem to love this stock. They've still kept the adjustable cheek piece and they've also added a number of M-Lok slots onto the fore end of the stock for your accessories, your bipods and what have you. One thing they have done away with though is this adjustment wheel for the cheek piece. The cheek piece on the Gauntlet II adjusts with two balance screws. Very simple to do and it's cut out a considerable amount of weight. That's an important enhancement here as well. Umarex wanted to keep the weight of the gun right about the same as the original Gauntlet and considering what they've added in a bigger bottle and a much beefier breech block assembly, you are talking about the same eight and a half pounds which is very impressive. Now starting at the front of the gun when we're talking about the differences between the original Gauntlet and the Gauntlet II, let's start with that bottle. So on the original Gauntlet you will remember in 22 caliber you are talking about a 13 cubic inch 3000 psi fill bottle with an 1100 psi regulator. Now in the Gauntlet II they have nearly doubled the size of the bottle. This is a 24 cubic inch bottle and the regulator pressure has been boosted to 1900 psi here in the 22. It's a little bit higher in the 25, just something to keep in mind there. Now again the original Gauntlet filled the 3000 psi which is great for you hand pumpers. The biggest change here for those of you out there that maybe don't have a tank or a compressor yet is the Gauntlet II fills to a full 4500 psi. So a much higher fill pressure and they've done that not only to go along with that higher reg pressure but also to maintain the stellar shot count that the original Gauntlet was known for. They claim over 70 shots in the 22 caliber here. Of course we're going to go ahead and put it to the test over the chronograph so we'll see how it comes in when it all shakes out. Now another big change that they've made between the original Gauntlet and the II is the bolt handle. Now one of the big complaints with the original Gauntlet was it was kind of stiff cocking. You know if you were trying to pull it back like a bolt action rifle it can be a little difficult. Personally not a big problem for me but I understand why most folks had that issue. So what Umrex has done with the G II is actually give you an upgraded bolt handle which is nice and beefy. You have a nice knurled end here and they've also managed to reduce the cocking effort by about 15 percent. That's what they say anyway. I don't have a good way to measure it but one thing I will tell you is that while it was a little stiff out of the box we put about a thousand shots through this now and it is super smooth and a lot easier than the original.  Super easy. If you try and operate this gun like a bolt action rifle and just holding that bolt you're going to have some difficulty. So that'll make your life a little bit easier but this is a very nice upgrade for Umrex. Now the last two changes we're going to talk about here are a bit more subtle. You've probably noticed already that the Gauntlet II sports a Picatinny rail on top here. Personally I like Picatinny mounts a lot it's a little bit easier to swap on and off take it off if you need to travel what have you but the nice thing about this is Umrex has actually secured these Picatinny rails on with set screws so the original 11 millimeter dovetail is still present.  Personally I'm going to stick to the Picatinny mounts but like I said it's a nice little option to have if you think you need it. The other change that they've made is to the baffle system. Now same shroud setup but obviously with the Gauntlet II you're talking about a lot more power so without redesigning the baffles they would have had a much louder gun. So in order to keep that nice low sound profile that the original Gauntlet was known for they've redesigned the baffles and you are still getting a very quiet experience. We'll obviously put it on the sound meter for you and you'll see for yourself but I think you will be impressed when we talk about how much power this is putting out and how little noise that's coming out of this thing. Now the rest of the features on the G2 are largely the same as what you had on the Gauntlet I. You still have your quick disconnect fill fitting. You have your pressure gauge on the other side. Your trigger safety is the same setup. You still have the same trigger which can be adjusted but you do need to remove the stock. You also have your degassing port and the tool for that is the same. Cocking function is the same as well. So when you want to go ahead and load your magazine you go ahead throw that bolt into the back section. You take your 10 round mag in 22 and you load it right into the breech there from the right hand side. Very simple and these are the same mags so you can reuse your original Gauntlet mags which is a nice touch also. A decocking procedure exactly the same. You hold that bolt back.  Decoct good to go now. Again as I mentioned before the cheek piece is still adjustable although the method to do that is a bit different and your sling swivel studs are also a bit different on this version. You have a QD mounting point at the back and then here at the front you're going to want to use one of those M-Lok slots to get an adapter and mount your sling that way. Other than that that's about the differences the similarities between the one and the two. Now let's get to the nitty gritty stuff and head out to the range and see how the Gauntlet II performs. All right so accuracy on the Gauntlet II in 22 caliber pretty solid results overall. You have the JSB standard monsters now these are the 25 4s. The heavy weights not the redesigns though just under an inch here for all 10 shots moving on the JSB 1813. You can see I threw one there but you have a 7 eighths inch group in total and three quarters of an inch 9 out of 10 very solid. The H&M Barracuda matches also did pretty well at a one inch group as well but the very best is the monster redesigned JSBs 5 eighths inch for all 10 shots. This is a stellar group exactly what we've come to expect from the Gauntlet line of guns and is going to create a ton of power but speaking of let's put the gun over the chronograph and see what these are doing. So taking our JSB Jumbo monster redesigns over the chronograph with the Gauntlet II you are looking at over 90 shots on a fill from 4500 PSI down to the reg pressure of 1900 PSI. That's really impressive they're only rating the gun for 70 or over so to get another 20 on top of that's really phenomenal obviously meaning you don't need to fill this gun all the way up to 4500 PSI to get a ton of shots so for you hand pumpers out there or those of you running on setups that maybe don't output 45 or 4350 or something like that you're still going to get plenty of shots but obviously almost 44 foot pounds of energy coming out of those monster redesigns with an extreme spread of just 10 feet per second and a standard deviation of just 1.7 feet per second the numbers are very impressive and if you compare them back to the original Gauntlet you are getting more shots now obviously that's coming with a higher fill pressure but you're getting way more power and way more shots and really that's what the Gauntlet II is doing for you it is building upon what was already pretty impressive. So let's run down the Gauntlet II here personally guys I think Umarex has done a great job of following up the original Gauntlet very hard thing to do with such a game changing rifle but they've taken this in a very cool direction they've created a real powerhouse airgun at just a few dollars more right around 400 bucks or so this gun packs a ton of power a ton of shots as you saw into a pretty nice package you know the gun is still 8.5 pounds it is on the heavier side of the market but it's not too bad to you know manage get around with and the stock changes while personally the aesthetic is not my favorite I like the color I just don't like the blockiness of the stock but it does feel good and it handles well also I love the incorporation of the unlock slots the fact that they've still managed to keep it quiet while upping the power to nearly 45 foot-pounds of energy in 22 is pretty insane and like I said before the shot count is phenomenal as well and most importantly this thing is damn accurate basically a little over a half inch group at 45 yards is stellar I mean that's exactly the high standard that the original Gauntlet set that the Gauntlet 2 is certainly carrying on so overall for me guys the Gauntlet 2 is a definite winner one I'm glad to see hit the market and one I hope you will all check out if you are looking to get into the PCP game and looking for a gun that can really reach out and touch something with authority as always hope you enjoyed today's video for the insider I'm Tyler Patner don't forget to follow us on Facebook Instagram like comment subscribe here on YouTube we appreciate it a ton and we'll see you at the next one


What's going on Infinite Family? Welcome back to another video. It's your girl Janice. If you guys are new to the channel, make sure you hit that subscribe button and join the family. Today, I am going to be pranking Isaiah. I know you guys are probably wondering, where's Isaiah? Well, he is actually getting some breakfast right now, so I had the time to do this intro, but I'm just going to go ahead and get straight to the point. So guys, you all know that Isaiah surprised me with a trip to Jamaica for my birthday, but today I'm going to be pranking him by telling him that I don't want to go to Jamaica anymore. Now, I know that's super crazy because you guys know, and Isaiah knows, that I wanted to go to Jamaica for as long as I can remember. It's been my dream. So for me to say something like that, he is going to be taken back like crazy.  You don't want to go to Jamaica anymore. But guys, I don't know what reason I'm going to give him. I'm probably going to tell him like, I just want to go to Turks and Caicos instead or I want to go to Cancun instead. I don't know. I'm just going to make something up on the spot. But I know you guys are going to get a good reaction out of him. And I know I'm going to get a good reaction out of him. So if you're ready for today's video, don't forget to smash that like button. Comment team Janice in the comment section below. So I'm going to wait until he gets home. I'm going to go ahead and set up the camera and we are going to get this prank started. Let's get it guys. It is time to get the pranking on. I saw Isaiah pull up. So I went ahead, I set up the camera. I'm going to have it rolling. And I'm just going to have it facing the table. Hopefully he comes in and he goes straight to the table. Because if not, this is going to be a fail. But let's cross our fingers that it's not going to be a fail. Don't forget again to smash that like button. Comment team Janice in the comment section below. And guys, let's freaking get it. Like paper straws. And that's what they were going to give you anyway. You said you didn't want anything. I'm just kidding. Don't be doing that because you'll be doing that. Turn around. What'd you get me? Let me guess. You got a bacon egg and tea, coffee. Oh yeah, see? I'm going to buy some stuff. So I'm going to take you some. Get some first and then I'm going to talk to you. Bro, nothing was coming up. There's a lot of chunks in there, huh? Chunks. Yeah, like lemon chunks. I see no chunks. I don't know what you're talking about. I do. That's all pulp right there. Like straight lemon. It tastes good. It tastes like lemonade. All right. Well, are you settled? I'm going to talk to you about something. That is a bacon egg and cheese thing. Yeah, it is and you can't have none. I know I can't. I have self-control. There's not even that. What is it? You can't have cheese. That's what I said. I can't have any of that anyway. But. Don't make my cool calls. Okay. I really hope that you're not going to get mad and I hope that you understand my perspective of it. Okay. That's yours. Like I actually want to be serious now. Okay, let's hear it. No joking or anything. Let's hear it. Okay. I don't want to go to Jamaica anymore. Okay, like that. I'm serious. Like this is why I say I want to be serious. I know we've never run a lot of stuff, but like, I'm in that serious. What do you mean you don't want to go to Jamaica anymore? Okay. So I was thinking about the whole trip and everything and it's nice and Jamaica is beautiful. So you're turning down Jamaica because it's not Turks and Caicos. Even though you've told me for the past three years that you've been wanting to go to Jamaica and all of a sudden now you don't want to go. Are you getting mad? Yeah, I'm kind of frustrated. Yes, I am. But why?  You've been talking about it for three years. This is your birthday gift.  This is why everyone wants to talk about it with you. All of a sudden you don't want to go to Jamaica? It's not all of a sudden. Do you know how much I paid for this trip? So? What do you mean? Why does it matter? That's a lot of money I spent.  That's not the point either though. You're going to tell me. But then why do you bring it up then? Because they're not going to be a full refund. They're going to charge a cancellation fee and all that. And it's like everything's inclusive. So I've got to cancel the flights. I've got to cancel the hotel. I've got to cancel this, that.  I've been talking about it more than three years. Okay, so what's the... Why? Why all of a sudden you know I don't want to go? Because I just felt like we took too long to take a trip somewhere out of the country. So now I'm like... It's the same thing if you were to go to Turks and Caicos. You're traveling at the same time. What do you mean? No, it's not that. I don't know. It's just more for... When you hear people say, Oh, I want to go on vacation. If you say, Oh, I'm going to Jamaica. Are you guys going to be like, Oh, yeah, whatever. Jamaica's okay, cool. But Turks and Caicos... Turks and Caicos has such a good breath. So you're doing this to look better in other people's point of view? Well, it doesn't matter. To make it seem better, to make it seem... It doesn't matter. I just want to go to Turks and Caicos. And that's what everybody talks about Turks and Caicos. Okay, so why can't... You never talk about Turks and Caicos. I'm talking about you.  I've got this gift solely for you based on what you said. I understand that.  But do you understand like how that would frustrate me? Especially with the amount of money that I'm not going to get 100% back. That was just a waste of money though. So is this all you care about is money? No, it's not the money. I'm frustrated because you told me you've been wanting to go to Jamaica for the past three years. I booked you Jamaica, right? I booked you your dream vacation. And now you're telling me you don't want it. One, that's kind of messed up. Two, I put a lot of thought and effort into like planning this whole thing. And then three, I'm not going to get 100% of the money back that I spent on it. Which is just a waste. So that don't give you the money. It's not about that. You're forgetting the other two things I said. Baby, you can't just take money and put it in Turks and Caicos. Baby. Literally take the money and put it right in Turks and Caicos. Everything's already booked. Now I got to book a whole another trip because you're not satisfied with Jamaica. That's kind of messed up. It's not messed up? Yes, it is messed up. But honestly, it's kind of like a little ungrateful if I'm being honest with you. Well, I don't care. I don't want to go to Jamaica anymore.  Me. I don't want to go anymore. All right, Selena, don't go. I'll go by myself. No, you're not going by yourself. I'm going to go to Turks and Caicos. You go do what you want then. Take me to Turks and Caicos. Seriously. That's what I'm asking for. Tell me about it.  How am I being a brat? Take me to Turks and Caicos. Since where are you like that? Yes, take me to Turks and Caicos. I deserve it.  Take me to Turks and Caicos. You need to quit.  What do you mean this ain't it?  I'm done with this conversation. I don't want to go to Jamaica anymore. So don't go. So I'm going to...  Yes, you are. You're going to pay for it and you're going to take me. Because that's what you're supposed to do. No. I don't have to do anything. I'm not supposed to do nothing. Oh, yes. You have to take me. No, I'm not. I do everything because I love you and because I'm trying to be a good boyfriend and show you that you deserve everything. And you're going to sit here and just give back or like not accept or be ungrateful for the things I'm trying to give you and it meant a lot. Like in a lot of effort and planning and you're just going to sit here and tell me, oh, I don't want to go to Jamaica. All right, so then don't go, bro. I'll go by myself. It's as simple as that. So you're really going to go to Jamaica without me? Yeah, I am. And so you're not going to change it to Turks and Caicos.  That's how I feel about that. That's the other hand sanitizer. I don't care. That's actually yours. I don't care. You're taking me to Turks and Caicos. You're ruining my meal. Smells weird. You can't ruin it. Oh, I can't, but I got you. So stay tuned to these. I'm not saying nothing. You started work. Stay tuned. Damn, babe. Why are you being so slow? It's like right now. Bro, just be quiet.  Like take me right now. I'm trying to be Kylie Jenner.  Like when you were getting like that, that was really like him.  That's like my biggest pet peeve, right, babe? Bratty females. Bratty children. Just brats in general. All right, I've been a fam so clear. My inner pageant queen. My inner like, I don't even know what. I was just trying to be the brattiest person ever. Like I finished the outro because you're not about rumors. Thank you. So it seems like you're pretty salty, but any notification shout out. Today's post notification shout out goes out to Raya underscore SS17 on Instagram. Thank you so much for your love and support. Izan, I love you. If you want to post notification shout out. All you guys got to do is like, comment, share and subscribe. Turn on your post notification bells so you're notified whenever we post a new video. And with all that being said, again, comment to your genies in the comment section below because we got that as and with all that being said again, we'll catch you in the next video.