Rewriting a legacy application in Elixir - Raphael Costa - ElixirConf Eu 2018

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hired run my name is rafael right so first of all don't get fooled by the fancy title CEO right because being a CTO on a small start-up means just like your developer with more work to do right so it's a very very underpaid position so i'm from brazil so yeah one thing that you should know about me is that I I am a very very very passionate elixir lover right so I had some experience with Ruby before and I really enjoyed the the all the features or the tooling but yeah for I never really felt like it was a the best tool to buy to build like a huge a big software right and I know some people do so yeah it's just my my personal feelings and I was reading the seven languages in seven weeks book by pragmatic programmers and I found about erling there right so then I immediately fell in love with Erlang model of process and actors right so the concurrency and the safety part really spoke to me so the first time I wrote a process and killed it and got to started so it like was like wow this is awesome right so but at the same time the syntax and the tooling didn't spoke to me like Ruby did so I was like okay I really like Ruby and it's fun to write code but I really enjoy her linked ways their link philosophy their language to do things and so I went to Google and I searched for early plus Ruby yeah that's actually the the search query I ran on Google and I think the first or second result was elixir homepage and it was like three years ago so three four years ago so it's funny because I was reading the an interview with Joseph Allen and he said his story was almost like mine right so he was he liked Ruby he but he was looking for something different and he found Erlang but apparently when he run this query he didn't find much right so so yeah that's how we got here well I work at this company if it's a service call this translates roughly to fiscal efficiency in English and what we do is make companies lives easier in Brazil because we have a very very crazy tax policy back in Brazil it's it's nuts right actually it's it's so crazy that a recent PwC research actually not that recent pointed out that Brazilian accountants spent 2006 in 600 hours per year per company doing taxes so it's crazy for a matter of comparison in the UK the number goes to 100 hours a 200 and something hours in Poland right so yeah so this opened a an opportunity for us to create this company and we try to pinpoint how much tax you should be and what kind of taxes you should pay for each product you're selling and it's a really good idea back in Brazil right so we even got featured on the 100 syrups watch in Brazil because of this our business model it's really appealing to people back there so first first of all this is not a web scale case right we don't have millions of concurrent users this is not our our problem with the that we try to solve it with elixir right so we have like 1,300 companies using our services and 900 active users so it's not a big number right we usually see like oh it's billion users using a software so no that's not our case but we have a high customer data ratio right so this small number of users generate 80 gigabytes of database storage and more than 50 million items that were already processed so it's a small number of customers and a huge number of data generated right so so that's the problem we have few a few paying customers and this load of stuff to do right so we must do as efficiency efficiently as we can because you can just like scale and add more servers forever right so the problem we had this huge monolith actually for for our our perspective it's a huge monolith because it was a small team so and efficiency Scott was built on top of this multi-tenant monolith so we had this application and when the idea for efficient surface cow started we okay let's he used we used this so yeah don't don't do that right it's crazy and we had food rot spreading really fast new things that we just wrote were getting legacy real quick it was really hard to maintain this and we still had paying users right so users were paying to use this so we couldn't just like okay let's scrap this and start over no that was an option and the product wasn't really done yet - right so we couldn't just okay let's stop creating new features and let's just port everything to elixir know that was an option either and to make things worse we had a small team sometimes just me so yeah now that's a thinker so yeah that was the issue and something I should have mentioned on the beginning of the talk is that I'm not even talking about which stack we were using because I don't want this to become a whole language is better than this one kind of comparison so but okay but we didn't use elixir that's for sure right so then we had this problem to solve the water what was the watcher it should make a request to an endpoint bars some XML check if the data change and send an email with the changes and repeat again in one hour so we have this problem to solve and yeah we didn't feel like our current stack would solve this well it was really a brittle right so if you can imagine on the the back of the room of the development room reason my handy I'm in know something to solve this right so I presented elixir to the team and people liked the idea and yeah then we chose the leeks you to stop this problem some of you some of you may be thinking seeing these requirements but okay you could you have used a cron job and some monitoring right yeah so the results we had turning 13 comets 13 comets and four days later to deploy this first application was deploying on 2015 August and a single comet commits a year later to do some refactoring and to up and running today right so it's still running and people were really really healthy happy with this win and this win will prove itself really helpful in our future problems right that you have to go through so then after this we had these other requirements that we had sure sorry receive two text files on an endpoint parse them and cross-reference them build this this data set and through putting through a lengthy audit process right this process is meant to find the correct text for that for the profits of the user so so far so so good right our current stack would be able to handle this but we had to make sure the thing runs until the end so yeah that that was a problem so that's when elixir came in people were like oh we had this kind of problem before when we need to make sure that something run right so yeah let's use the leak sir again and for our luck phoenix 1.0 had just been launched it right if you see the dates back there no no if anyone everyone will be able to 2020 28th of august right so it was it was like ten days after this article was was posted so that we decided to create this with phoenix and yeah we build it and it was a lot faster than anything else we could had ever built using WebSockets for live updates of the the process this was nice because we could go to the stakeholders INSEAD to see this updating number here yeah this wouldn't be possible right so it was a nice way to sell elixir to the remainder of the company and the thing ran and to the right so that was the the biggest the biggest win so and an indirect thought is that the code was really nice read really nice you to change so yeah seeing that and seeing what we achieved using elixir we decided to begin the migration in this migration had all these requirements that i told before we couldn't just stop developing new features we couldn't just scrap everything and start over no we had to keep both applications running and migrating things bit by bit so we had like this structure we have an inking and Linux server pointing all the requests to the legacy application then we added a new rule everything with /p would go to the Phoenix application if anyone is seeing this and going like oh okay there's that's the way I can do to rewrite an application bit by bit yeah don't do that right don't take notes right now I'll show a better way down the road so yeah we came up with this and yes I don't know I think most an experienced functional programmers went through this where you can it's hard to think about how to solve something functionally so you try to part everything you know from the other language right so yeah that's one thing that we we try to do we try to rewrite things actually rewriting not porting solutions you were rewriting codes so yeah you can imagine that it was kind of messy so we had two problems with this with our approach the first one the legs application was too messy for oh let's just move things yeah we should have seen this coming right it's not a hard problem to predict but yeah we we had this and the second problem the thing was seeing the Phoenix app as a secondary application right so because of this /p this odd thing on the routes that led to the Phoenix application people were seeing okay this is like some secondary application we should just use it when our main application doesn't right and that there's a learning curve in functional programming in the leak sir and in Phoenix right so people weren't wasn't willing to go through this learning curve so they weren't seeing the value of using the leaks are using Phoenix so yeah we had we had this problem and then the migration came to turn out right we spend I think four months without any commits on the Phoenix repo and things kind of just stopped it right so yeah then okay let's change things change things let's try to do things differently first we decided to use Phoenix as a reverse proxy to the legacy application gladly this library terraform was just released right and by reading this there was this article this companion article right rise from the ashes it's a really nice read if you are willing to migrate something to elixir I really highly recommend you for reading this so we decided to use this and at first there that was some skepticism about latency oh this will add some unnecessary overhead to our response time but yeah whatever I didn't we so we had this new structure because we had the very heavy front-end very GS heavy fronting most of our logical relied on AP is right so I have this slash API endpoints but usually went to the legacy application so what we did is to redirect this on NX to the Phoenix app right and using terraform if any if there wasn't any routes that could match these endpoints it will go back to the legacy application take the response and give it to the client right just like a reverse proxy and the overhead was less than one millisecond so it was really really fast the usual response times were around 200 milliseconds so it didn't make any difference on our perception of the application so yeah that's one thing that we did differently the other one was no more just porting the logic that's right functional code you know and let's let's solve the problems in a functional way let's not just look at our other solutions and pour them that's what I call the the leaks away right it's the yeah like the path of the alchemists or something so we did this we changed our way to creating the solutions in the new application and one more thing is that we model the application as an umbrella because as I told before we have a lot of data right so most of our load is not a web related it's background processing so we have like this this background services that have to do their stuff periodically do some sinking do some processing so this switching architecture was was kind of funny because usually we have the chill options right monolith and microservices and mono leaf wasn't the right one for us because we had just been out of a monolith we weren't willing to enter another one so you got striped out very quickly and micro-services I really considered using microservices for some time but after seeing some talks and doing some reading I got the conclusion that micro services are not a way to structure your code structure your your domain right it's a way to structure our teams so if you have a small team like we had micro services will add some benefits of keeping things separated but would add an overhead to our development process that we wouldn't be able to cope with so yeah that one was out too so we had we were looking for this or what's the magical option that will solve all of our problems right so we ended up with elixir umbrellas they are very nice and neat way to splitting your codebase into multiple applications without all the overhead of of having micro services and yeah you can do both you can deploy the deployed applications separately so you don't have to deploy everything the whole thing as a single unit you can you can choose what applications in your umbrella you are willing to the play so yeah ok so what happened then the team walls went up so yeah people were no longer seeing Phoenix as the secondary application mostly because they saw how fast it can be they saw how reliable it can be when you put it on the front of the legacy application so this had a huge impact on the team's morale the code became easier to refactor reason about so we have a have a a more maintainable code base and things were moving smoothly and management was happy because they were seeing the improvements of the the new stack so yeah life was good right so everything was working and we have this whole plan on the migration and everything we're doing ok this code is is good it's shiny new application the shiny code but this happens then we were just like this huge Phoenix application okay yeah yeah we're like this again so that's life right yeah but for some time I tried to avoid the this change on the the Phoenix architecture and it worked right you know there's a thing that you're not doing and you like okay there's no problem but it it's it comes back to haunt you sometimes right so I I had this this closure moment when I was explaining our architecture our the way we manage code right to a new developer a torching and he didn't get anything he was like I don't understand how this works right why should I put things why should I look for things and for me it was easy because I got used to that structure but for a new person that's when I saw hey this is not good so I gave a try to Phoenix context and yeah they are good they are good the first context I wrote i ported some logic to this context and then I showed him the the code and the tests and he was like okay now I get this so it was really easy it's it's really nice reason about how to structure code and yeah so that's there's a I think I think Chris is doing a keynote on the ending of today right so I hope he doesn't get no surprises right yeah so okay so today we have over thirty six thousand lines of code in elixir and growing actually had to update this slide three times because we had first twenty eight then thirty then 36 it's it's growing pretty fast we have three developers including me right the CEO two interns right training with elixir and our umbrella currently has eleven applications I think for four of them are deployable right so the other seven are just dependences just libraries right and yeah okay so I never intended this talk to be like okay ten steps migrator absolutely so you know so just a story of what happened and what we did that worked and what I did that didn't work but so there are some things that we did that might help you right if you are anyone here like about to migrate something to elixir yeah yeah okay so some things that we did that really helped us one of them credo credo yeah I don't know how to say that so it's very nice it's a really good library the thing about you know who uses cradle here okay cool thing about it is that it ensures a consistent code base it find helps finding simple problems and avoids questions regarding style it's like the the code formatter you shouldn't be discussing about or two spaces first places tabs right no we should discuss about business problems solving real problems right and the the for mother for matter is doing a really good job right now but there are some things that it's outside of the grasp of the formatter and credo covers it about function complexity and having documentation and yeah it's a really nice library and it avoids discussions like oh that that committee made you should add documentation to the module no cradle does this right so I really encourage any anyone who's writing legal to use credo and most of all start with credo because one thing is when you start your project using cradle cradle from the beginning and another thing is when you have like this huge pile of code in the rancor cradle on it and it finds like 200 warnings right so using from the beginning is always always the best properly testing right this is this is awesome this is awesome andressa go is giving a talk on this later so i'm not going to go out too much on it and yeah but it helps catching bugs on edge cases and it helps test in complex features more easily right so you have this complex function that has many many conditionals so you write this bunch of tests to cover all the paths right or the function using properly testing you can just encode this variances this conditionals on your property right and it you wind up with one test that test is the whole thing so it's really easy to get a good coverage of a code base a full coverage actually with a small effort writing tests so yeah that's it'll be included in the the new elixir Jose I said but you can use it today with the stream data library so moving on and another thing that might help is using elixir unique capabilities to solve problems right so when you when you get to a problem you have to find a solution sometimes it's easier to go to what you already know right so on my previous stack I would solve this like this right I use this solution this tooling and elixir opens up for a whole bunch of different ways to solving things and most of the time this new exciting ways makes makes the solutions elegant and more resilience or reliable then it would be right so and this using this using this elixir unique capabilities to solving these problems also helps showing a management showing the team that ok you see this this works because of elixir right so yeah and it's not it's not that hard to do that actually hearing what I just said I wanted to be careful to not over engineer things right it's not the same thing yeah an example we have this very very simple code okay we have this background processing job that should do something with all the companies in our code base and it this thing means accessing and sterno endpoints and unknowing point and a very very unreliable endpoints so we couldn't just create very parallel workers who do things in maximum concurrence you know this would like DDoS their services right so yeah but we needed to do this very simple so what did we do this function had only the it doesn't actually call do thing right it's just and code example right so the but the actual function that goes here just has the happy path right everything works and we have monitoring we use apps I know right now and okay so you have the head path you have monitoring ship it okay so yeah because when you're communicating to an external endpoints you have all these multiple failure modes right things can blow up in the most unexpected ways so we couldn't account for all of them but we did it to do this so okay we ship it the code it ran sometimes but we had a problem right yeah that's that's common sorry soft development what was a problem when an error happens to the second company all the other 1,000 or so we didn't do anything right so yeah we had this problem or where errors were happening early on the list of companies and things were just hot see so okay how do you solve this one way we thought about was to add some try-catch here on the on this function and in case of errors manually sending them to epsilon so we can see later what work it's what didn't right because we didn't care if some companies fail we just scared that anything everything was processed and we got to know of any surprises right so my first C synced was to do this let's put a try/catch and yeah and send the errors reps I know so but then I started reading about reading the tasks module documentation and the task supervisor documentation and I got you this solution right so you have a task supervisor you don't have to actually start it on the on the on the spot right you can have a list a super desk supervisor on the supervision three other application so we have the supervisor and we just call task supervisor a sync string no link this very small function and what it does basically a creates a string of tasks right that where I could run this function for every company in a separate task that wasn't linked it to our process right so yeah what happened things still failed we had some some companies that couldn't fetch their data but they were isolated now so we doesn't matter and the S every process that dies on the Bing we got to know later through monitoring monitoring yeah so yeah we if you include the desk start test to providers start link line we went from one to three lines to solve the problem right so yeah and this is working flawlessly it's so it's this kind of stuff this kind of problem that you wouldn't be able to solve like this or would take a lot more time to do in your older stack so yeah this should the management or and mostly to the team that's working on the application this is its code right because they see the power on the new platform so some closing thoughts this most of our problems we had were like a year two years ago something like that and the leisure landscape was very very different back then we have much more a lot of tutorials a lot of articles a lot of material and example shoe base on right so I expect people who embark on this journey of migrating things this huge application to elixir to don't go on too many too much turbo as we did right and one thing that I can't stress enough is this book I wish we had this book so I started reading it I read the first two parts of it and it pointed it this book pointed out so many errors that we did back then and had to suffer the consequences right so it's an awesome book if you're willing to migrate to elixir I cannot recommend this book enough so yeah I think that's it thank you Thank You Hoffa so we have time for about three questions so hi I'd like to ask is the migration over first and second during the migration how did you handle authentication between the two legacy services for things like database schemas migration and all this kind of no yeah duplicated stuff that you have yeah actually the two applications used shared database it's a very it's a very classic structure right you have the database the application and they communicate and they use the same database right now but as a rule to help enforce this elixir way of doing things and because act or didn't have the schema definition of columns back then - right we have this rule where every time we needed some table from the legacy application into the elixir application we will migrate data right so create new tables all the tables the old tables had prefixes the columns have suffixes it's yeah it's crazy crazy odd to work with so every time we had to port part things to the application we had this rule right okay let's part the data to let's restructure the data while migrating and then making some adjustments on the legacy application so just so things didn't break right and we also had a radius database for some session communication between on and what about authentication how did you migrate passwords from some users to the new system passwords did you have yeah yeah yeah that's that's interesting that's an interesting question what we did was first we had to port the old password hashing logic to the elixir application right so yeah I had to analyze how the Hessian worked and brought it back so after we did this we did this we had two columns on the database like the old hash and the new hash right and we are now using I forgot the name of the application the the library but we first try using the new hashing method and and then if the columns new or something like that we go go back to the we fall back to the old method and every time a users switch passwords they go to the new hash right so we keep both applications happy and for logins we are using JWT right so we have this shared certificate between both applications so they both can understand the same token how did you deal with problems or were there any problems round tripping things like JSON where the internal representation and alexia could be different from that of Ruby or rails I'm sorry I couldn't hear that the question as they're better how did you deal with the internal representation of things like JSON data when it's round tripped so if you're storing for example in the new API data that then goes back in and comes out again in the rails side yeah like changing the JSON format right for the return of the endpoints yeah yeah okay so first it's it's not a rails app the legacy one right but yeah that's one thing we ran into we were quite nave before think that we could all let's just replace the endpoints and things will just work we won't need to touch anything on the front end yeah that's not how it worked we had to change the front end so yeah but since since we were solving the problems in a more functional way no more just sports in code that wasn't that much of an issue because all the screens on the front side of the application needed some refreshing right so we took the chance to improve them I'm right so let's give our speaker closing round of applause [Music] [Applause] you
Info
Channel: Erlang Solutions
Views: 4,498
Rating: 4.9139786 out of 5
Keywords: Elixir
Id: P9z9UIidVxE
Channel Id: undefined
Length: 43min 54sec (2634 seconds)
Published: Wed May 02 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.