blob: 0e68b1b0336fda632f386a8d8b7c62bd15f9dd0b [file] [log] [blame]
<!doctype html>
<!--
Minimal Mistakes Jekyll Theme 4.4.1 by Michael Rose
Copyright 2017 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE.txt
-->
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<!-- begin SEO -->
<title>SecKill Develop Journey (III) - Apache ServiceComb</title>
<meta name="description" content="an introduction how build seckill demo project step by step">
<meta name="author" content="Yangyong Zheng">
<meta property="og:locale" content="en">
<meta property="og:site_name" content="Apache ServiceComb">
<meta property="og:title" content="SecKill Develop Journey (III)">
<link rel="canonical" href="https://github.com/pages/apache/incubator-servicecomb-website/docs/seckill-development-journey-part-III/">
<meta property="og:url" content="https://github.com/pages/apache/incubator-servicecomb-website/docs/seckill-development-journey-part-III/">
<meta property="og:description" content="an introduction how build seckill demo project step by step">
<meta name="twitter:site" content="@ServiceComb">
<meta name="twitter:title" content="SecKill Develop Journey (III)">
<meta name="twitter:description" content="an introduction how build seckill demo project step by step">
<meta name="twitter:url" content="">
<meta name="twitter:card" content="summary">
<meta name="twitter:creator" content="@">
<meta property="og:type" content="article">
<meta property="article:published_time" content="2017-09-07T00:00:00+08:00">
<script type="application/ld+json">
{
"@context" : "http://schema.org",
"@type" : "Person",
"name" : "Apache ServiceComb",
"url" : "https://github.com/pages/apache/incubator-servicecomb-website",
"sameAs" : null
}
</script>
<meta name="google-site-verification" content="HvJjNd7vvJ-yjSTHlBiIWEYxp_Hrz-PYEY5Idz9LRcA" />
<!-- end SEO -->
<link href="/feed.xml" type="application/atom+xml" rel="alternate" title="Apache ServiceComb Feed">
<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>
<script src="/assets/vendor/prism/prism.js"></script>
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<script src="https://www.apachecon.com/event-images/snippet.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<!-- For all browsers -->
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="stylesheet" href="/assets/vendor/prism/prism.css">
<!--[if lte IE 9]>
<style>
/* old IE unsupported flexbox fixes */
.greedy-nav .site-title {
padding-right: 3em;
}
.greedy-nav button {
position: absolute;
top: 0;
right: 0;
height: 100%;
}
</style>
<![endif]-->
<meta http-equiv="cleartype" content="on">
<!-- start custom head snippets -->
<!-- insert favicons. use http://realfavicongenerator.net/ -->
<link href="https://fonts.loli.net/css?family=Roboto:400,500,700|Source+Code+Pro" rel="stylesheet">
<script src="/assets/js/custom.js"></script>
<!-- end custom head snippets -->
</head>
<body class="layout--single">
<!--[if lt IE 9]>
<div class="notice--danger align-center" style="margin: 0;">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</div>
<![endif]-->
<div class="masthead" onmouseleave="$('#childrenShow').css('display', 'none')">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title active" href="/"><img src="https://www.apache.org/img/servicecomb.png"></a>
<ul class="visible-links">
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/developers/">Projects</a>
</li>
<li class="def-nav-li" onmouseenter="$('#childrenShow').css('display', 'block')">
<a href="/docs/users/">Documentation</a>
<ul id="childrenShow" class="def-children-show-en" onmouseleave="$('#childrenShow').css('display', 'none')">
<li><a href="/docs/getting-started/" class="">Getting started</a></li>
<li><a href="/docs/users/" class="">Docs</a></li>
<li><a href="/slides/" class="">Video</a></li>
<li><a href="/faqs/" class="">FAQ</a></li>
</ul>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/year-archive/">Blogs</a>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/release/">Downloads</a>
</li>
</ul>
<button><div class="navicon"></div></button>
<ul class="hidden-links hidden"></ul>
<div class="nav-lang">
<a href=/cn/docs/seckill-development-journey-part-III/>中文</a>
</div>
</nav>
</div>
</div>
</div>
<div id="main" role="main">
<div class="sidebar sticky">
<div class="back-to-home"><a href="/">Home</a> > SecKill Develop Journey (III)</div>
<div itemscope itemtype="http://schema.org/Person">
<div class="author__content">
<h3 class="author__name" itemprop="name">Yangyong Zheng</h3>
<p class="author__bio" itemprop="description">
Fast Action, do not ask
</p>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li>
<a href="https://zhengyangyong.github.io" itemprop="url">
<i class="fa fa-fw fa-chain" aria-hidden="true"></i> Website
</a>
</li>
<li>
<a href="mailto:yangyong.zheng@huawei.com">
<meta itemprop="email" content="yangyong.zheng@huawei.com" />
<i class="fa fa-fw fa-envelope-square" aria-hidden="true"></i> Email
</a>
</li>
<!--
<li>
<a href="http://link-to-whatever-social-network.com/user/" itemprop="sameAs">
<i class="fa fa-fw" aria-hidden="true"></i> Custom Social Profile Link
</a>
</li>
-->
</ul>
</div>
</div>
</div>
<article class="page" itemscope itemtype="http://schema.org/CreativeWork">
<meta itemprop="headline" content="SecKill Develop Journey (III)">
<meta itemprop="description" content="an introduction how build seckill demo project step by step">
<meta itemprop="datePublished" content="September 07, 2017">
<meta itemprop="dateModified" content="September 13, 2017">
<div class="page__inner-wrap">
<header>
<h1 class="page__title" itemprop="headline">SecKill Develop Journey (III)
</h1>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
2 minute read
</p>
</header>
<section class="page__content" itemprop="text">
<p><a href="/docs/seckill-development-journey-part-II/">Previous article</a> we had built a full-featured seckill demo, release it version 0.1.0-RELEASE; now you should find that data persistence is centered on a single database, seckill is high-stress scenario, it’s difficult to meet high-scalable requirement, and as we mentioned at the beginning, micro-service is recommended to have independent storage, so we will start using Event Sourcing implement CQRS pattern to enhance the ability to endure huge requests.</p>
<h2 id="cqrs">CQRS</h2>
<p>CQRS means Command Query Responsibility Segregation, it’s a powerful design pattern, often implement with Event Sourcing, there has a figure describe it from Microsoft MSDN:</p>
<p><img src="/assets/images/seckill-develop-course-part-III-cqrs.png" alt="Fig-1 CQRS" class="align-center" /></p>
<h2 id="improvement-design">Improvement Design</h2>
<p>CQRS is read write separation and message-driven best practices, now we focus on the MySQL database:</p>
<ol>
<li>The database should be split into ReadDB and WriteDB,read-intensive Query micro-service and write-intensive Command micro-service should be independent;</li>
<li>ReadDB and WriteDB using Event Message drive data synchronization, so we need add a new micro-service named Event(Processor);</li>
<li>Message Broker currently has a lot of great implements, such as RabbitMQ, Kafka, etc., because our seckill based on ServiceComb and Spring Boot, in order to be able to quickly build this new feature, we use built-in ActiveMQ, which supports memory queue mode, very easy to build Testing, suitable for agile development approach</li>
</ol>
<p>Now the latest Architecture below:</p>
<p><img src="/assets/images/seckill-develop-course-part-III-arch-en.png" alt="Fig-2 CQRS improved Architecture" class="align-center" /></p>
<h2 id="improvement-implement">Improvement Implement</h2>
<h3 id="database-separation">Database Separation</h3>
<h4 id="writedb">WriteDB</h4>
<p>Admin micro-service maintain Promotion entity;</p>
<p>Command micro-service write PromotionEvent Value-Object,when recovery Promotion,Relapy PromotionEvent.</p>
<h4 id="readdb">ReadDB</h4>
<p>Event micro-service write ActivePromotion Value-Object and Coupon Value-Object;</p>
<p>Query micro-service query ActivePromotion Value-Object and Coupon Value-Object.</p>
<h4 id="command-micro-service-message-publisher-component">Command micro-service Message Publisher component</h4>
<p>Since the Event Sourcing was not introduced before, the PromotionEvent entity only needed to write to the database directly. Now it is necessary to publish PromotionEvent to Message Broker. Considering that future we will be replaced by Distributed Message Service (DMS) as Message Broker in order to deploy to <a href="http://www.hwclouds.com/">Huawei Cloud</a>, We defined the generic message publish interface:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">SecKillMessagePublisher</span> <span class="o">{</span>
<span class="kt">void</span> <span class="nf">publishMessage</span><span class="o">(</span><span class="nc">String</span> <span class="n">messageContent</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>
<h4 id="event-micro-service-implement">Event micro-service implement</h4>
<p>Event micro-service subscribe Message Broker in order to get PromotionEvent Message, then depending on the message type convert to ActivePromotion Value-Object operation or Coupon Value-Object operation in ReadDB.</p>
<ul>
<li>Promotion Start Message: create ActivePromotion Value-Object;</li>
<li>Promotion Finish Message: delete ActivePromotion Value-Object var Id;</li>
<li>
<p>Coupon Grabbed Message: create Coupon Value-Object;</p>
<p>Also considering that future we will be replaced by Distributed Message Service (DMS) as Message Broker in order to deploy to <a href="http://www.hwclouds.com/">Huawei Cloud</a>, We defined the generic message subscribe interface:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">SecKillMessageSubscriber</span> <span class="o">{</span>
<span class="kt">void</span> <span class="nf">subscribeMessage</span><span class="o">(</span><span class="nc">String</span> <span class="n">messageContent</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div> </div>
</li>
</ul>
<h4 id="update-of-query-micro-service">Update of Query micro-service</h4>
<p>After the refactoring of the read and write separation, all activing Promotion are saved in ActivePromotion Value-Object Table, and customers own Coupon are stored in Coupon Value-Object Table, now we can directly query them, no longer need Replay PromotionEvent.</p>
<h2 id="all-in-one-start-up">All-In-One start-up</h2>
<p>Now, we have complete Event Sourcing architecture refactoring, in order to be easy to start-up, we provide docker compose script, use it pull all services up by one command, see detail at <a href="https://github.com/ServiceComb/seckill">SecKill</a>.</p>
<h3 id="start-up-all-service-in-docker-toolbox">start-up all service in Docker ToolBox</h3>
<p><img src="/assets/images/seckill-develop-course-part-III-seckill-all-in-one.png" alt="Fig-3 SecKill All-in-One" class="align-center" /></p>
<h2 id="reference">Reference</h2>
<ol>
<li><a href="https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs">Command and Query Responsibility Segregation (CQRS) pattern</a> by Microsoft Azure Team</li>
<li><a href="https://msdn.microsoft.com/en-us/library/jj591559.aspx">Introducing Event Sourcing</a> by Microsoft patterns &amp; practices Developer Center</li>
<li><a href="https://martinfowler.com/eaaDev/EventSourcing.html">Event Sourcing</a> by Martin Fowler</li>
</ol>
</section>
<footer class="page__meta">
<p class="page__taxonomy">
<strong><i class="fa fa-fw fa-tags" aria-hidden="true"></i> Tags: </strong>
<span itemprop="keywords">
<a href="/tags/#seckill" class="page__taxonomy-item" rel="tag">seckill</a>
</span>
</p>
<p class="page__date"><strong><i class="fa fa-fw fa-calendar" aria-hidden="true"></i> Updated:</strong> <time datetime="2017-09-13">September 13, 2017</time></p>
</footer>
<section class="page__share">
<h4 class="page__share-title">Share on</h4>
<a href="https://twitter.com/intent/tweet?via=ServiceComb&text=SecKill Develop Journey (III) /docs/seckill-development-journey-part-III/" class="btn btn--twitter" title="Share on Twitter"><i class="fa fa-fw fa-twitter" aria-hidden="true"></i><span> Twitter</span></a>
<a href="https://www.facebook.com/sharer/sharer.php?u=/docs/seckill-development-journey-part-III/" class="btn btn--facebook" title="Share on Facebook"><i class="fa fa-fw fa-facebook" aria-hidden="true"></i><span> Facebook</span></a>
<a href="https://plus.google.com/share?url=/docs/seckill-development-journey-part-III/" class="btn btn--google-plus" title="Share on Google Plus"><i class="fa fa-fw fa-google-plus" aria-hidden="true"></i><span> Google+</span></a>
<a href="https://www.linkedin.com/shareArticle?mini=true&url=/docs/seckill-development-journey-part-III/" class="btn btn--linkedin" title="Share on LinkedIn"><i class="fa fa-fw fa-linkedin" aria-hidden="true"></i><span> LinkedIn</span></a>
</section>
<nav class="pagination">
<a href="/cn/docs/seckill-development-journey-part-II/" class="pagination--pager" title="秒杀开发历程(二)
">Previous</a>
<a href="/cn/docs/seckill-development-journey-part-III/" class="pagination--pager" title="秒杀开发历程(三)
">Next</a>
</nav>
</div>
<div class="page__comments">
<section id="static-comments">
<!-- Start static comments -->
<div class="js-comments">
</div>
<!-- End static comments -->
<!-- Start new comment form -->
<h4 class="page__comments-title">Leave a Comment</h4>
<p class="small">Your email address will not be published. Required fields are marked <span class="required">*</span></p>
<form id="new_comment" class="page__comments-form js-form form" method="post" action="https://api.staticman.net/v1/entry/apache/incubator-servicecomb-website/master">
<div class="form__spinner">
<i class="fa fa-spinner fa-spin fa-3x fa-fw"></i>
<span class="sr-only">Loading...</span>
</div>
<fieldset>
<label for="comment-form-message">Comment <small class="required">*</small></label>
<textarea type="text" rows="3" id="comment-form-message" name="fields[message]" tabindex="1"></textarea>
<div class="small help-block"><a href="https://daringfireball.net/projects/markdown/">Markdown is supported.</a></div>
</fieldset>
<fieldset>
<label for="comment-form-name">Name <small class="required">*</small></label>
<input type="text" id="comment-form-name" name="fields[name]" tabindex="2" />
</fieldset>
<fieldset>
<label for="comment-form-email">Email address <small class="required">*</small></label>
<input type="email" id="comment-form-email" name="fields[email]" tabindex="3" />
</fieldset>
<fieldset>
<label for="comment-form-url">Website (optional)</label>
<input type="url" id="comment-form-url" name="fields[url]" tabindex="4"/>
</fieldset>
<fieldset class="hidden" style="display: none;">
<input type="hidden" name="options[slug]" value="seckill-develop-course-part-III">
<label for="comment-form-location">Not used. Leave blank if you are a human.</label>
<input type="text" id="comment-form-location" name="fields[hidden]" autocomplete="off"/>
</fieldset>
<!-- Start comment form alert messaging -->
<p class="hidden js-notice">
<strong class="js-notice-text"></strong>
</p>
<!-- End comment form alert messaging -->
<fieldset>
<button type="submit" id="comment-form-submit" tabindex="5" class="btn btn--large">Submit Comment</button>
</fieldset>
</form>
<!-- End new comment form -->
</section>
</div>
</article>
<div class="page__related">
<h4 class="page__related-title">You May Also Enjoy</h4>
<div class="grid__wrapper">
<div class="grid__item">
<article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork">
<h2 class="archive__item-title" itemprop="headline">
<a href="/cn/docs/playing-on-the-open-source-community-with-Apache-ServiceComb-GDUT/" rel="permalink">与Apache ServiceComb一起玩开源-广工站 (PPT Download)
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">与Apache ServiceComb一起玩开源-广工站 (PPT Download)
</p>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
less than 1 minute read
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork">
<h2 class="archive__item-title" itemprop="headline">
<a href="/cn/docs/servicecomb-service-center-client/" rel="permalink">使用ServiceComb客户端轻松调用ServiceCenter
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">使用ServiceComb客户端轻松调用ServiceCenter
</p>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
2 minute read
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork">
<h2 class="archive__item-title" itemprop="headline">
<a href="/cn/docs/playing-on-the-open-source-community-with-Apache-ServiceComb-BUPT/" rel="permalink">与Apache ServiceComb一起玩开源-北邮站 (PPT Download)
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">与Apache ServiceComb一起玩开源-北邮站 (PPT Download)
</p>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
less than 1 minute read
</p>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork">
<h2 class="archive__item-title" itemprop="headline">
<a href="/docs/servicecomb-accept-newcapec-institute-code-donation/" rel="permalink">Apache ServiceComb Accept Code Donation From NewCapec Institute
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">Apache ServiceComb Accept Code Donation From NewCapec Institute
</p>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
less than 1 minute read
</p>
</article>
</div>
</div>
</div>
</div>
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<div align="center" style="margin: 0 0;">
<ins class="adsbygoogle"
style="display:block; border-bottom: initial;"
data-ad-client="ca-pub-7328585512091257"
data-ad-slot="3049671934"
data-ad-format="auto"></ins>
</div>
<div class="page__footer">
<footer>
<!-- start custom footer snippets -->
<!-- end custom footer snippets -->
<div class="container">
<div class="row justify-content-md-center">
<div class="col">
<ul>
<p class="header">Events</p>
<a class="acevent" data-format="square" data-mode="dark" data-event="random"></a>
</ul>
</div>
<div class="col">
<ul>
<p class="header">Resources</p>
<li><a href="/docs/getting-started/">Getting started</a></li>
<li><a href="/docs/users/">User Guide</a></li>
<li><a href="/slides/">Slides</a></li>
<li><a href="/users/faq/">Common Questions</a></li>
</ul>
</div>
<div class="col">
<ul>
<p class="header">ASF</p>
<li><a href="http://www.apache.org">Foundation</a></li>
<li><a href="http://www.apache.org/licenses/">License</a></li>
<li><a href="http://www.apache.org/events/current-event">Events</a></li>
<li><a href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="http://www.apache.org/foundation/thanks.html">Thanks</a></li>
</ul>
</div>
<div class="col">
<ul>
<p class="header">Contribute</p>
<li><a href="http://issues.apache.org/jira/browse/SCB">Report a Doc Issue</a></li>
<li><a href="https://github.com/apache/servicecomb-website/edit/master/_posts/2017-09-07-seckill-develop-course-part-III.md">Edit This Page on Github</a></li>
<li><a href="/developers/submit-codes/">Code Submit Guide</a></li>
<li><a href="/security">Security</a></li>
</ul>
</div>
<div class="col">
<ul class="social-icons">
<p class="header">Community</p>
<li>
<a href="mailto:dev-subscribe@servicecomb.incubator.apache.org" rel="nofollow"><span class="mail">Mailing List</span></a>
</li>
<li>
<a href="https://github.com/apache?q=ServiceComb" target="_blank"><span class="github">Github</span></a>
</li>
<li>
<a href="https://twitter.com/ServiceComb" target="_blank"><span class="twitter">Twitter</span></a>
</li>
<li>
<a href="/feed.xml" target="_blank"><span class="rss">Feed</span></a>
</li>
</ul>
</div>
</div>
</div>
<div class="page__footer-bottom">
<div>&copy; 2024 Apache ServiceComb. Powered by <a href="http://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div>All other marks mentioned may be trademarks or registered trademarks of their respective owners.</div>
</div>
</footer>
</div>
<script src="/assets/js/main.min.js"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-101622733-1', 'auto');
ga('send', 'pageview');
</script>
<script>
(function ($) {
var $comments = $('.js-comments');
$('#new_comment').submit(function () {
var form = this;
$(form).addClass('disabled');
$('#comment-form-submit').html('<i class="fa fa-spinner fa-spin fa-fw"></i> Loading...');
$.ajax({
type: $(this).attr('method'),
url: $(this).attr('action'),
data: $(this).serialize(),
contentType: 'application/x-www-form-urlencoded',
success: function (data) {
$('#comment-form-submit').html('Submitted');
$('.page__comments-form .js-notice').removeClass('notice--danger');
$('.page__comments-form .js-notice').addClass('notice--success');
showAlert('Thanks for your comment! It will show on the site once it has been approved.');
},
error: function (err) {
console.log(err);
$('#comment-form-submit').html('Submit Comment');
$('.page__comments-form .js-notice').removeClass('notice--success');
$('.page__comments-form .js-notice').addClass('notice--danger');
showAlert('Sorry, there was an error with your submission. Please make sure all required fields have been completed and try again.');
$(form).removeClass('disabled');
}
});
return false;
});
function showAlert(message) {
$('.page__comments-form .js-notice').removeClass('hidden');
$('.page__comments-form .js-notice-text').html(message);
}
})(jQuery);
</script>
</body>
</html>