Distributed Scheduling with Spring Boot: the challenges & pitfalls of implementing a background job

Поделиться
HTML-код
  • Опубликовано: 12 янв 2025

Комментарии • 168

  • @linhvudev
    @linhvudev 7 месяцев назад +12

    Thanks Rafael! especially for the SKIP_LOCKED feature, new knowledge learnt

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад +4

      Thank you so much! I am glad the talk was helpful for you! 🥰
      And yeah, SKIP LOCKED is fantastic!! 💪🏻

  • @eduardo120155
    @eduardo120155 6 месяцев назад +9

    Congratulations on your presentation! You absolutely nailed it. Your thorough research and confident delivery captivated everyone in the room. Your ability to explain complex ideas so clearly is truly impressive. Keep up the fantastic work!

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад

      Thanks for the kind words, Eduardo! ❤

  • @terteseamos579
    @terteseamos579 6 месяцев назад +4

    this for me is the best presentation. Great job

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад +1

      What a comment! Thanks for that! ❤️

  • @codeisma
    @codeisma 7 месяцев назад +9

    Great talk! There are a few Java libraries that already solve these challenges (db-scheduler, JobRunr or Quartz). At JobRunr we'd love to share your talk as it explains JobRunr's architecture well and can help our users understand the challenges of distributed scheduling even better!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад +5

      Thanks for your comment! I'm glad you liked it! ☺
      Please, I would appreciate it if you shared it! By the way, I received great feedback from Ronald, the creator of JobRunr-he watched my talk! He is a fantastic guy! ❤

    • @RonaldDehuysser
      @RonaldDehuysser 7 месяцев назад +1

      @@RafaelPonte You're too kind 🤩!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      ⁠@marshall143Thanks for the comment! 😊 I didn't know nFlow, but I understand that if your context allows your team or project to adopt a task scheduler or workflow engine, you should go with it.
      Usually, those libs and frameworks make the developer's life easier because they address very well all the issues discussed in the talk.

  • @felipedossantos7246
    @felipedossantos7246 6 месяцев назад +2

    I've seen this presentation in portuguese before of Rafael Pontes in Zup Channel, and I could implement something similar it in my job. Great work, Bro! Thank you so much

    • @RafaelPonte
      @RafaelPonte 5 месяцев назад +1

      Hi Felipe,
      Thanks for this comment and for having watched both versions of the talk. ❤

  • @RaphaelDeLio
    @RaphaelDeLio 7 месяцев назад +7

    Parabéns, Rafael! Foi um prazer assistir sua apresentação pessoalmente!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Obrigado demais, Rapha! ❤ Você eh top!

  • @popastefan6542
    @popastefan6542 5 месяцев назад +1

    36:48 Actually in our example, each instance will fight for first 50 records, not one record as it is illustrated in the slide.

    • @RafaelPonte
      @RafaelPonte 5 месяцев назад

      Thanks for the comment.
      Yeah, you're right. The number of rows is unimportant in understanding how the SQL feature works. The idea was to be didactic and straightforward.

  • @YZ-ix3dn
    @YZ-ix3dn 6 месяцев назад +2

    Thank you for clear and well-structured presentation. It's very useful and important information even for people with lots years of experience. I wish every developer should watch this video when every time they put @Transactional onto theirs method.

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад

      Thanks for the kind words! I am glad you enjoyed the talk! ☺

  • @bkavun
    @bkavun 6 месяцев назад +1

    Great presentation, great work. Thanks a lot for sharing this knowledge with us!

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад +1

      Thanks so much! I am glad you liked it 🥳

  • @hirenpandit8499
    @hirenpandit8499 6 месяцев назад +1

    Great talk!! so much learnings and addressed real life problems I faced while writing background scheduled jobs... btw we used ShedLock library but this is real good insight.

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад

      Thanks! Nice you liked it!! 😊
      By the way, ShedLock is a very cool library! 👊🏻

  • @ferlezcano
    @ferlezcano 7 месяцев назад +1

    Excellent topic! Have some background jobs running here and there and I definitely going to check them again.

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад +1

      Nice! I am glad this talk was helpful to you! 👊🏻

  • @danielponte3134
    @danielponte3134 7 месяцев назад +2

    Parabéns meu irmão , você deu um show na apresentação, impecável! show de top!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Obrigado, meu irmão!

  • @gustadev276
    @gustadev276 Месяц назад +1

    Que talk boa, aprendi tanta coisa que fiquei até perdido!

    • @RafaelPonte
      @RafaelPonte Месяц назад

      Obrigado pelo feedback! ☺ Feliz que teve conteudo novo, bom e útil pra você!

  • @balazsklezli5877
    @balazsklezli5877 Месяц назад +1

    It was pretty cool talk, thank you for it!

    • @RafaelPonte
      @RafaelPonte Месяц назад

      You're welcome! I am glad you liked it! ☺

  • @matthewmoore5934
    @matthewmoore5934 5 месяцев назад +1

    Great talk! A couple of thoughts. Your statement about entity state and transactions is only true if Spring's "open session in view" is not enabled. I find there is a lot of confusion out there about the Hibernate session, transaction state, OSIV, and entity state. Along similar lines, the call to a repository save() method is unnecessary when updating an attached entity because of Hibernate change tracking, and calling save() leads people to assume that it persists changes, which (counterintuitively) it doesn't. (It adds/merges detached entities to the session/persistence context.) Regarding transaction scope, I would argue it is still too broad. Work for a single user/card should generally happen in its own transaction, at least in an OLTP context.

    • @RafaelPonte
      @RafaelPonte 5 месяцев назад +1

      You are welcome! Thanks for the comment ☺️
      I am unsure if I followed your comment about Open Session in View. I mean, there's no OSIV relation to a job scheduled by Spring since OSIV has to do with web/MVC scope. The code in the talk is correct.
      You are right about the save() method; it wasn't needed, but the idea was to show a simple and didact code, not getting into details about how to persist entities or their state transitions.
      The transaction scope is broader because we are working in batches 😊

    • @matthewmoore5934
      @matthewmoore5934 5 месяцев назад +1

      @@RafaelPonte Thanks for the response. I spend much time working in a WebMVC context that (unfortunately) uses OSIV and I'm too used to its oddities. 🙂

  • @hamedalipour1012
    @hamedalipour1012 7 месяцев назад +1

    you are an amazing presenter thank you so much learned a lot

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Thank you so much!!! I am happy this talk was helpful for you 🥳

  • @jessilyneh
    @jessilyneh 7 месяцев назад +1

    Congrats for your amazing presentation, Rafa!

  • @knoppix20
    @knoppix20 5 месяцев назад +2

    26:34, 31:59, 32:14, 36:04, 40:31 - key moments

    • @RafaelPonte
      @RafaelPonte 5 месяцев назад +1

      Thanks for the comment and for pointing out the key moments ☺️

  • @paulorcv
    @paulorcv 5 месяцев назад +1

    Very good! thank your for the valuable content!

    • @RafaelPonte
      @RafaelPonte 5 месяцев назад

      You are welcome 🤗

  • @jesprotech
    @jesprotech 7 месяцев назад +4

    I really like the way you explained short running transactions. Nice addition to the jobs! Parabéns pela excelente apresentação! É muito útil!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Thanks so much! I am glad you liked it 🥰

  • @pavanerbeck23
    @pavanerbeck23 6 месяцев назад +1

    Nicely done @RafaelPonte.

  • @CodingForRealLife
    @CodingForRealLife 5 месяцев назад +1

    Amazing persentation, very usefull, thanks Rafael!

    • @RafaelPonte
      @RafaelPonte 5 месяцев назад

      You are welcome! 😊

  • @mindcontrolkmc.3286
    @mindcontrolkmc.3286 6 месяцев назад +1

    Really great talk!
    But I am curious that if 2 save statements already wrap in 1 small transaction how can it combine with the hibernate batch with another save statement process

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад

      Thanks for the comment and feedback 😊
      I am not sure if I understood your question correctly. Could you elaborate a little bit more on it?

    • @mindcontrolkmc.3286
      @mindcontrolkmc.3286 6 месяцев назад +1

      Hi Rafael,
      In the scenario of this video, we are using short-transaction to save data to the database so I think each transaction should be isolated so they can't be wrapped in one batch like your example INSERT INTO ... Values (A),(B)

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад

      @@mindcontrolkmc.3286 Yeah, the idea is precisely that! For each batch (chunk) of 50 rows, Hibernate will group (and reorder if needed) each INSERT and UPDATE inside that short-running transaction and convert them into only two single statements right on the commit.

  • @gjperes1
    @gjperes1 7 месяцев назад +1

    O Rafael é fera demais!! Great presentation

  • @HariharanIyer
    @HariharanIyer 7 месяцев назад +1

    Great talk and lot of cool new (for me) information about Spring/JPA semantics! But not much of this is specific to background jobs, and not much in the talk about generic background job processing. So I'd say the title is a bit misleading.

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Thanks for the comment 😊 I am glad the content was helpful for you!
      Out of curiosity, what do you understand as background jobs and job processing, and what do you expect from a talk about these subjects?

  • @Cassitu
    @Cassitu 7 месяцев назад +1

    Parabeeens manooo! ficou top! sucesso

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Obrigado! Feliz que curtiu ❤

  • @duyetpham7924
    @duyetpham7924 7 месяцев назад +1

    Beautiful presentation, thank you

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Thank you so much! That's very nice you liked it! 🥰

  • @simongeard4824
    @simongeard4824 4 месяца назад +1

    As a side note, the original example program has one further problem which wasn't discussed - if the job runs every 60 seconds, what happens if it takes more than 60 seconds to complete, giving you unintended parallel processing? I've been bitten by that one a few times...

    • @RafaelPonte
      @RafaelPonte 4 месяца назад +2

      Thanks for the comment! 😊
      In the context of the talk, this is not an issue. I mean, Spring will not allow running multiple jobs for the same task, even if it takes longer than 60 sec.
      But if the method is annotated with @Async then we can not say the same 😬

    • @simongeard4824
      @simongeard4824 4 месяца назад +1

      @@RafaelPonte Fair enough... you're right that a good scheduler will avoid the problem (for sync operations, at least). My negative experiences have typically been with more naive scheduling tools...

    • @michaelchung8102
      @michaelchung8102 3 месяца назад +1

      ​@@RafaelPonte Does it mean the while-true loop is also fine? And how will Spring behave if the job takes slightly longer than 60 seconds? Will it let it complete the last batch process iteration?

    • @RafaelPonte
      @RafaelPonte 3 месяца назад +2

      @@michaelchung8102 Spring will not stop or kill the thread running the job. Since the while-true loop has a break statement, the job will run until all the filtered rows from the table are processed, and it's ok if this execution takes more than 1 minute.
      After that, the Spring Scheduler will wait 1 minute before starting the same job again.
      Does it make sense?

    • @michaelchung8102
      @michaelchung8102 3 месяца назад +1

      @@RafaelPonte oh yes, I forget that without Async, Spring will just queue the jobs if previous ones are still running, thanks for your quick reply, and a big thanks to you as this video answers the doubts about race condition and performance concerns in distributed scheduling that I had for years. ❤️

  • @YuliSlabko
    @YuliSlabko 6 месяцев назад +1

    Nice explanation! But did not cover very important case if your app has more than one job marked with @Scheduled annotation. Because it may be crucial moment of performance. May be it will be covered in next topics.

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад

      Thanks for the comment 😊 Nice you liked it!
      I am not sure if I understood what you mean. Usually, a single application has multiple @Scheduled jobs running concurrently doing different things (sometimes at other times).
      Could you give more details?

    • @YuliSlabko
      @YuliSlabko 6 месяцев назад +1

      @@RafaelPonte If you do not specify in application.yml thread pool size for scheduler explicitly all jobs will be operated by one single thread.

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад +1

      ​@@YuliSlabko Thanks for the explanation. Now I got your point! ☺
      You're right. If your application runs multiple jobs close together or jobs that take too long to finish, tuning the Scheduler's thread pool size is essential. 👊🏻

  • @SarkhanTakhirov
    @SarkhanTakhirov 6 месяцев назад +1

    what's the difference between reading and writing with a rabbit or kafka and reading and writing with a database?
    Usually i'm using REDIS for solve same problem, because it much faster than usual relation db

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад

      Thanks for the comment.
      I will ignore the trade-offs of having a new component in the infrastructure now and focus only on the developer's perspective.
      There are differences, but how they can impact your solution depends on your context. I mean, using Kafka or RabbitMQ in the talk's job perspective may have little difference on the job's code, but in the application perspective, which produces events in the queue, we may have to deal with a dual write issue.
      The same is true for Redis: it depends on how you're using it, such as a distributed lock provider or a message queue.

  • @aleksandrS3894
    @aleksandrS3894 6 месяцев назад +1

    Does a single @Transactional annotation for Scheduled method (in case of JPA framework) fix the original code right away?

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад

      Thanks for the comment.
      It depends on which problem you're talking about.
      In the talk’s context, it solves only part of the problem: it makes the whole operation atomic and recoverable but causes a few side effects.

  • @victoralcantara8470
    @victoralcantara8470 7 месяцев назад +1

    Amazing! Congrats Rafa!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Thanks, I'm glad you liked it ☺

  • @ruff7209
    @ruff7209 Месяц назад +1

    Perfect! thx Rafael!

  • @lobaorn
    @lobaorn 7 месяцев назад +1

    Congrats Rafael! Parabéns Rafa!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Thanks so much!!! 🥰

  • @fonfux0123
    @fonfux0123 4 месяца назад +1

    Essa abordagem serve para todos os modelos de banco ou há algum diferencial entre eles por exemplo o Oracle?

    • @RafaelPonte
      @RafaelPonte 4 месяца назад

      Obrigado pelo comentário! 😊
      Eu discuti vários problemas e soluções na talk, e a maioria roda bem com a maioria dos bancos relacionais, mas podem sim haver nuances. De qual abordagem vc fala exatamente?

    • @fonfux0123
      @fonfux0123 4 месяца назад +1

      ⁠bom dia Rafael eu tentei usando Oracle 12c subindo 2 instâncias no ecs mas ao executar um job que busca do banco e publica em um tópico as instâncias trazem registros repetidos! Parabéns pela live de ontem no deveficiente! Agora tb serei seu aluno lá

    • @RafaelPonte
      @RafaelPonte 4 месяца назад

      @@fonfux0123 valeu!
      então, Oracle suporta bem o que discuti na talk. Como está o SELECT executado pela aplicação? Ele está sendo gerado FOR UPDATE ou FOR UPDATE SKIP LOCKED?

    • @fonfux0123
      @fonfux0123 4 месяца назад +1

      @@RafaelPonte com for update skip locked! acho que tem algo a ver com os cursores do oracle como funcionam! posso estar enganado! ou entao o fato de eu estar delimitando a qtd de registros da consulta e ele so da o lock depois de obter o resulta pra cada uma das linhas

    • @RafaelPonte
      @RafaelPonte 4 месяца назад

      @@fonfux0123 Entendi.
      Isso é verdade. No caso do SKIP LOCKED, o Oracle somente faz o locking durante o fetching do registro, e não durante a seleção (filtering) do mesmo. Mas isso normalmente acontece quando você está manipulando explicitamente cursores via PL/SQL ou alguma API de persistência.
      Aqui nessa outra talk sobre SKIP LOCKED focada em Oracle, eu comento essa "limitação": ruclips.net/video/8DVFc7gXfIQ/видео.html
      Espero que ajude!

  • @TTT-z2l
    @TTT-z2l 7 месяцев назад +1

    Great talk! Did not catch all the red flags in this :)

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Thanks! I am glad you liked it!! ❤

  • @顾清l
    @顾清l 7 месяцев назад +1

    In my understanding, `select ... limit 50 for update` would directly lock these 50 rows, instead of locking one row and processing one row at a time. But in the video, it seems to be the latter approach. Why is that?

    • @wukash999
      @wukash999 7 месяцев назад +1

      He just presents it like that for a purpose of presentation. Of course it will lock all 50 rows (as long as they meet select criteria and are not locked already). Overall this is a very basic presentation, not sure what was the point of that.

    • @RaphaelSousa-or1dl
      @RaphaelSousa-or1dl 7 месяцев назад +3

      @@wukash999 I think the point is to introduce to more unexperienced people the possibles problems one might encounter, so you can study further on it (at least for me it worked ,since I've never thought or knew about this problems), not to make a thourough implementation guide

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Thanks for your comment ☺
      As @wukash999 commented, the idea was to make it as didactic and accessible as possible so that junior and inexperienced developers could understand it.
      Do you think it got confused?

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      @@wukash999 Thanks for your comment and helping them to understand my intention ☺
      Do you think this was an introductory and basic talk? I'm afraid I have to disagree. The talk was designed to simplify the subject and make it accessible for everyone, but it's still a complex, tricky, and detailed theme.

    • @yonishachar1887
      @yonishachar1887 4 месяца назад +2

      @@wukash999 How is that a very basic presentation? How would you implement it differently?

  • @BlindVirtuoso
    @BlindVirtuoso 2 месяца назад +1

    Nice one. Appreciate it.

    • @RafaelPonte
      @RafaelPonte 2 месяца назад

      Thanks! I am glad you liked it ☺️

  • @rabah4306
    @rabah4306 7 месяцев назад +1

    @Transactional Will this works if You have to call a mongoRepositoy and Kafka template ?
    All or nothing
    If Kafka call KO
    The mongo call also ?

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Thanks for your comment ☺
      Although MongoDB and Kafka support some level of transactions, I don't know how @Transactional annotation would work with MongoRepositories or KafkaTemplates. It's worth reading the Spring Data docs.
      But it's important to be aware that you do NOT have an atomic operation (all or nothing) when your code mixes different external service calls, like PostgreSQL, Mongo, and Kafka. When you do that, you hit a common issue in distributed systems called "dual write".

    • @asterixcode
      @asterixcode 7 месяцев назад +1

      @@RafaelPonte I have the same use case where i need to write to mongo, kafka and also to google cloud storage bucket within the same transaction. Do you by any chance know how to solve this problem so I get a all or nothing? Or if not possible, how we would solve this problem then….

    • @rabah4306
      @rabah4306 7 месяцев назад +1

      @@RafaelPonte obrigado :)

    • @MrKar18
      @MrKar18 6 месяцев назад +1

      For mongo, you can spin a new session with transaction as well, manually. However for Kafka if the produced records are idempotent, you can use the mongo transaction support above to achieve the same.

  • @annabeatrizelias9689
    @annabeatrizelias9689 7 месяцев назад +2

    Parabéns, muito show!

  • @JuniorAdy10
    @JuniorAdy10 7 месяцев назад +1

    Braaabo de mais. Parabéns, príncipe do oceano kkk 👏👏👏

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Brigadão, Junior! 👊🏻

    • @benicioavila
      @benicioavila 7 месяцев назад +1

      @@RafaelPonte Parabéns Rafael! Compartilhando com todos do meu time! Abraço.

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      @@benicioavila obrigado ☺️ E valeu por compartilhar!! ❤️

  • @zickzack987
    @zickzack987 7 месяцев назад +2

    Ummm...
    Distribution topic starts after 27 min.
    Using db locks is tricky and works differently for different databases, e.g. lock escalation. Better use an app level locking.
    All that had not really to do a lot with jobs. Just long running tasks in a distributed system.

    • @RaphaelSousa-or1dl
      @RaphaelSousa-or1dl 7 месяцев назад +2

      Do you have a resource recommendation on app level locking? I'm studying the topic and it would be awesome to see it more detailed. Thanks

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад +2

      Thanks for your comment ☺
      Distributed systems are tricky, and database locks have worked well for over 30 years. Although some databases might differ, an exclusive row-level lock works similarly. By the way, a few RDBMS suffer from lock escalation, but not PostgreSQL (which was used in the talk's context); in addition to that, we used many approaches in the talk that mitigate the chances of lock escalation 💪🏻
      Regarding application-level locking, PostgreSQL offers Advisory Locks as an excellent alternative to row-level locks. They're very light and are handled by the application side.

  • @MrDaniloko23
    @MrDaniloko23 6 месяцев назад +1

    Great content!

  • @eddwinpaz
    @eddwinpaz 7 месяцев назад +1

    Adorei a conversa, mas não sei se queria falar sobre Spring Boot ou se candidatar a político, hahaha.. brincadeira!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Hahaha, valeu! 😊

  • @DevMultitask
    @DevMultitask 7 месяцев назад +1

    Great job Rafael!

  • @rommelcosta6548
    @rommelcosta6548 7 месяцев назад +1

    excellent lecture 💚

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад +1

      Thanks, my friend!

  • @TJ-hs1qm
    @TJ-hs1qm 7 месяцев назад +1

    Is he describing Spark 😆?

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад +1

      Thanks for the comment 😊
      Do you mean Apache Spark? hehe

  • @tahahajivand1843
    @tahahajivand1843 5 месяцев назад +1

    it was so good.
    thanks

    • @RafaelPonte
      @RafaelPonte 5 месяцев назад

      I am glad you liked 😊

  • @lacerdaph23
    @lacerdaph23 7 месяцев назад +2

    Rafa is humble, Freak and beatifiul

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Hehe, you're very kind, my friend! ❤

  • @DiegoFerreiradaSilva
    @DiegoFerreiradaSilva 7 месяцев назад +1

    mandou bem, parabéns!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Obrigado, Diego ❤️

  • @adyanto4043
    @adyanto4043 5 месяцев назад +1

    The thing i hate the most in this video - "Conluding...", i was so engaged didnt wanted him to stop.

    • @RafaelPonte
      @RafaelPonte 5 месяцев назад

      hahaha, thank you so much for this lovely comment 🙏🏻😍 I am thrilled after reading it!!

  • @knoppix20
    @knoppix20 5 месяцев назад +2

    Ola. Todo bem

    • @RafaelPonte
      @RafaelPonte 5 месяцев назад +1

      Tudo ótimo ☺️☺️

  • @gsledoux
    @gsledoux 7 месяцев назад +1

    Parabéns marajá! 😉

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Brigadão ☺️☺️

  • @brunobrasilweb
    @brunobrasilweb 7 месяцев назад +1

    Parabéns Rafael, Zerou game do Java.

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      hahaha, valeu bruno!!!

  • @satishakumar1073
    @satishakumar1073 3 месяца назад +2

    Perfect

  • @lhsantos89
    @lhsantos89 7 месяцев назад +1

    What a prince 💛🔥

  • @davi.mustafa
    @davi.mustafa 7 месяцев назад +1

    é o cara! boooraa!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад +1

      Valeu Mustafa 👊🏻

  • @metrocartao
    @metrocartao 6 месяцев назад +1

    Muito bom!

    • @RafaelPonte
      @RafaelPonte 6 месяцев назад

      que massa que gostou 😊

  • @thiagonunes3619
    @thiagonunes3619 7 месяцев назад +1

    Nice!!

  • @ereboucas
    @ereboucas 7 месяцев назад +1

    Almost made me want to work with boring techs again ;)

    • @andreas_bergstrom
      @andreas_bergstrom 7 месяцев назад +1

      I’m moving back to Java/JVM after 15 years in Node/JS/Python

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Boring techs are amazing! 🙌🏻

  • @flavioecintia
    @flavioecintia 7 месяцев назад +1

    boa ponte!!!!!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Valeu, Flávio 😊

  • @gleicianylemos8824
    @gleicianylemos8824 7 месяцев назад +1

    👏👏👏

  • @mustafaabdsh
    @mustafaabdsh 7 месяцев назад +1

    thank you

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      you're welcome! ☺

  • @gabrielm6849
    @gabrielm6849 5 месяцев назад

    sorry, the topic and the presentation has,without doubt, a high technical value, but the english of this guy, the accent and the way he tries-hard to emphasise almost each and every word in the sentence comes highly unnatural.. it really sounds tiring in the ear

  • @fbarrosoflf
    @fbarrosoflf 7 месяцев назад +1

    Congrats, nice job!

    • @RafaelPonte
      @RafaelPonte 7 месяцев назад

      Thanks, Barroso! 👊🏻