mirror of
https://github.com/AderKonstantin/aderktech-chronark.com-.git
synced 2025-06-08 05:38:41 +03:00
22 lines
25 KiB
JSON
22 lines
25 KiB
JSON
{
|
|
"published": true,
|
|
"title": "QStash",
|
|
"description": "QStash is a fully managed serverless queue and messaging service designed for the serverless era.",
|
|
"date": "2022-07-18T00:00:00.000Z",
|
|
"url": "https://upstash.com/qstash",
|
|
"body": {
|
|
"raw": "\nQStash is an HTTP based messaging and scheduling solution for the serverless and edge runtimes.\n\n- 100% serverless, no stateful connections required. Messages are pushed to your API.\n- At-least-once delivery guaranteed to any public API\n- Pubsub via topics\n- Delay message delivery\n- Message deduplication\n- Scheduling via CRON\n\n\nFormally, QStash is a message queue and task scheduler designed for serverless runtimes. Informally, QStash is a glue for your serverless functions.\n\nThere was a perception serverless was only good for simple tasks. Not anymore. People build powerful systems with serverless stack. Powerful systems are composed of multiple components. Communication among those components is a big engineering problem. There are already great solutions for this problem. But we think existing solutions do not fit in serverless space. Either they are too complex or not designed to work with stateless runtimes. So we want a solution which (is):\n\n- Works anywhere including serverless and edge.\n- Messaging as a service with no backend for users to run.\n- Lightweight, easy to understand, requires nothing to learn.\n- Price scales to zero.\n\nLet's talk about a real world example. We have an e-commerce app and we want to send an informational email after each purchase. We have a service (an API route) for new purchases (newPurchase) and a second service for sending emails and notifications (sendEmail). We can call the sendEmail service from the newPurchase service. But what if the call fails? Should we wait for the response and retry? What if too many calls congest the sendEmail service and the service does not respond on time? You need to handle all these cases in your newPurchase service. Moreover, when you change the contract of sendEmail service; you have to update your newPurchase service too.\n\nIf you use QStash in the above example, you simply send a request to QStash from the newPurchase service. QStash will queue the request and call the sendEmail service. If the service does not respond, QStash will retry with a backoff strategy. The latency of sendEmail service will not affect the newPurchase service, because it will not wait for a response from the sendEmail service. QStash decouples the newPurchase and sendEmail services. You can update both services independently as long as you keep the message format compatible.\n\nWith QStash, you can add delays to the requests. Send an email 3 days after the shipment to remind the customer to add a review. You can also schedule tasks. You can send the requests with a CRON expression, so it will be run repetitively.\n\n\nTo learn more about QStash, visit [upstash.com/qstash](upstash.com/qstash).",
|
|
"code": "var Component=(()=>{var ur=Object.create;var F=Object.defineProperty;var cr=Object.getOwnPropertyDescriptor;var lr=Object.getOwnPropertyNames;var fr=Object.getPrototypeOf,dr=Object.prototype.hasOwnProperty;var B=(l,t)=>()=>(t||l((t={exports:{}}).exports,t),t.exports),hr=(l,t)=>{for(var v in t)F(l,v,{get:t[v],enumerable:!0})},Ee=(l,t,v,y)=>{if(t&&typeof t==\"object\"||typeof t==\"function\")for(let g of lr(t))!dr.call(l,g)&&g!==v&&F(l,g,{get:()=>t[g],enumerable:!(y=cr(t,g))||y.enumerable});return l};var mr=(l,t,v)=>(v=l!=null?ur(fr(l)):{},Ee(t||!l||!l.__esModule?F(v,\"default\",{value:l,enumerable:!0}):v,l)),br=l=>Ee(F({},\"__esModule\",{value:!0}),l);var we=B((Er,ke)=>{ke.exports=React});var xe=B(z=>{\"use strict\";(function(){\"use strict\";var l=we(),t=Symbol.for(\"react.element\"),v=Symbol.for(\"react.portal\"),y=Symbol.for(\"react.fragment\"),g=Symbol.for(\"react.strict_mode\"),G=Symbol.for(\"react.profiler\"),X=Symbol.for(\"react.provider\"),H=Symbol.for(\"react.context\"),T=Symbol.for(\"react.forward_ref\"),U=Symbol.for(\"react.suspense\"),A=Symbol.for(\"react.suspense_list\"),j=Symbol.for(\"react.memo\"),I=Symbol.for(\"react.lazy\"),je=Symbol.for(\"react.offscreen\"),K=Symbol.iterator,Pe=\"@@iterator\";function Se(e){if(e===null||typeof e!=\"object\")return null;var r=K&&e[K]||e[Pe];return typeof r==\"function\"?r:null}var k=l.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;function h(e){{for(var r=arguments.length,n=new Array(r>1?r-1:0),a=1;a<r;a++)n[a-1]=arguments[a];Ce(\"error\",e,n)}}function Ce(e,r,n){{var a=k.ReactDebugCurrentFrame,s=a.getStackAddendum();s!==\"\"&&(r+=\"%s\",n=n.concat([s]));var u=n.map(function(i){return String(i)});u.unshift(\"Warning: \"+r),Function.prototype.apply.call(console[e],console,u)}}var Oe=!1,De=!1,Fe=!1,Ue=!1,Ae=!1,J;J=Symbol.for(\"react.module.reference\");function Ie(e){return!!(typeof e==\"string\"||typeof e==\"function\"||e===y||e===G||Ae||e===g||e===U||e===A||Ue||e===je||Oe||De||Fe||typeof e==\"object\"&&e!==null&&(e.$$typeof===I||e.$$typeof===j||e.$$typeof===X||e.$$typeof===H||e.$$typeof===T||e.$$typeof===J||e.getModuleId!==void 0))}function We(e,r,n){var a=e.displayName;if(a)return a;var s=r.displayName||r.name||\"\";return s!==\"\"?n+\"(\"+s+\")\":n}function Z(e){return e.displayName||\"Context\"}function p(e){if(e==null)return null;if(typeof e.tag==\"number\"&&h(\"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.\"),typeof e==\"function\")return e.displayName||e.name||null;if(typeof e==\"string\")return e;switch(e){case y:return\"Fragment\";case v:return\"Portal\";case G:return\"Profiler\";case g:return\"StrictMode\";case U:return\"Suspense\";case A:return\"SuspenseList\"}if(typeof e==\"object\")switch(e.$$typeof){case H:var r=e;return Z(r)+\".Consumer\";case X:var n=e;return Z(n._context)+\".Provider\";case T:return We(e,e.render,\"ForwardRef\");case j:var a=e.displayName||null;return a!==null?a:p(e.type)||\"Memo\";case I:{var s=e,u=s._payload,i=s._init;try{return p(i(u))}catch{return null}}}return null}var E=Object.assign,R=0,ee,re,ne,ae,te,oe,ie;function se(){}se.__reactDisabledLog=!0;function Ye(){{if(R===0){ee=console.log,re=console.info,ne=console.warn,ae=console.error,te=console.group,oe=console.groupCollapsed,ie=console.groupEnd;var e={configurable:!0,enumerable:!0,value:se,writable:!0};Object.defineProperties(console,{info:e,log:e,warn:e,error:e,group:e,groupCollapsed:e,groupEnd:e})}R++}}function Me(){{if(R--,R===0){var e={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:E({},e,{value:ee}),info:E({},e,{value:re}),warn:E({},e,{value:ne}),error:E({},e,{value:ae}),group:E({},e,{value:te}),groupCollapsed:E({},e,{value:oe}),groupEnd:E({},e,{value:ie})})}R<0&&h(\"disabledDepth fell below zero. This is a bug in React. Please file an issue.\")}}var W=k.ReactCurrentDispatcher,Y;function P(e,r,n){{if(Y===void 0)try{throw Error()}catch(s){var a=s.stack.trim().match(/\\n( *(at )?)/);Y=a&&a[1]||\"\"}return`\n`+Y+e}}var M=!1,S;{var $e=typeof WeakMap==\"function\"?WeakMap:Map;S=new $e}function ue(e,r){if(!e||M)return\"\";{var n=S.get(e);if(n!==void 0)return n}var a;M=!0;var s=Error.prepareStackTrace;Error.prepareStackTrace=void 0;var u;u=W.current,W.current=null,Ye();try{if(r){var i=function(){throw Error()};if(Object.defineProperty(i.prototype,\"props\",{set:function(){throw Error()}}),typeof Reflect==\"object\"&&Reflect.construct){try{Reflect.construct(i,[])}catch(_){a=_}Reflect.construct(e,[],i)}else{try{i.call()}catch(_){a=_}e.call(i.prototype)}}else{try{throw Error()}catch(_){a=_}e()}}catch(_){if(_&&a&&typeof _.stack==\"string\"){for(var o=_.stack.split(`\n`),m=a.stack.split(`\n`),f=o.length-1,d=m.length-1;f>=1&&d>=0&&o[f]!==m[d];)d--;for(;f>=1&&d>=0;f--,d--)if(o[f]!==m[d]){if(f!==1||d!==1)do if(f--,d--,d<0||o[f]!==m[d]){var b=`\n`+o[f].replace(\" at new \",\" at \");return e.displayName&&b.includes(\"<anonymous>\")&&(b=b.replace(\"<anonymous>\",e.displayName)),typeof e==\"function\"&&S.set(e,b),b}while(f>=1&&d>=0);break}}}finally{M=!1,W.current=u,Me(),Error.prepareStackTrace=s}var x=e?e.displayName||e.name:\"\",ye=x?P(x):\"\";return typeof e==\"function\"&&S.set(e,ye),ye}function Ve(e,r,n){return ue(e,!1)}function Le(e){var r=e.prototype;return!!(r&&r.isReactComponent)}function C(e,r,n){if(e==null)return\"\";if(typeof e==\"function\")return ue(e,Le(e));if(typeof e==\"string\")return P(e);switch(e){case U:return P(\"Suspense\");case A:return P(\"SuspenseList\")}if(typeof e==\"object\")switch(e.$$typeof){case T:return Ve(e.render);case j:return C(e.type,r,n);case I:{var a=e,s=a._payload,u=a._init;try{return C(u(s),r,n)}catch{}}}return\"\"}var O=Object.prototype.hasOwnProperty,ce={},le=k.ReactDebugCurrentFrame;function D(e){if(e){var r=e._owner,n=C(e.type,e._source,r?r.type:null);le.setExtraStackFrame(n)}else le.setExtraStackFrame(null)}function qe(e,r,n,a,s){{var u=Function.call.bind(O);for(var i in e)if(u(e,i)){var o=void 0;try{if(typeof e[i]!=\"function\"){var m=Error((a||\"React class\")+\": \"+n+\" type `\"+i+\"` is invalid; it must be a function, usually from the `prop-types` package, but received `\"+typeof e[i]+\"`.This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.\");throw m.name=\"Invariant Violation\",m}o=e[i](r,i,a,n,null,\"SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED\")}catch(f){o=f}o&&!(o instanceof Error)&&(D(s),h(\"%s: type specification of %s `%s` is invalid; the type checker function must return `null` or an `Error` but returned a %s. You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).\",a||\"React class\",n,i,typeof o),D(null)),o instanceof Error&&!(o.message in ce)&&(ce[o.message]=!0,D(s),h(\"Failed %s type: %s\",n,o.message),D(null))}}}var Qe=Array.isArray;function $(e){return Qe(e)}function Be(e){{var r=typeof Symbol==\"function\"&&Symbol.toStringTag,n=r&&e[Symbol.toStringTag]||e.constructor.name||\"Object\";return n}}function ze(e){try{return fe(e),!1}catch{return!0}}function fe(e){return\"\"+e}function de(e){if(ze(e))return h(\"The provided key is an unsupported type %s. This value must be coerced to a string before before using it here.\",Be(e)),fe(e)}var N=k.ReactCurrentOwner,Ge={key:!0,ref:!0,__self:!0,__source:!0},he,me,V;V={};function Xe(e){if(O.call(e,\"ref\")){var r=Object.getOwnPropertyDescriptor(e,\"ref\").get;if(r&&r.isReactWarning)return!1}return e.ref!==void 0}function He(e){if(O.call(e,\"key\")){var r=Object.getOwnPropertyDescriptor(e,\"key\").get;if(r&&r.isReactWarning)return!1}return e.key!==void 0}function Ke(e,r){if(typeof e.ref==\"string\"&&N.current&&r&&N.current.stateNode!==r){var n=p(N.current.type);V[n]||(h('Component \"%s\" contains the string ref \"%s\". Support for string refs will be removed in a future major release. This case cannot be automatically converted to an arrow function. We ask you to manually fix this case by using useRef() or createRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref',p(N.current.type),e.ref),V[n]=!0)}}function Je(e,r){{var n=function(){he||(he=!0,h(\"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)\",r))};n.isReactWarning=!0,Object.defineProperty(e,\"key\",{get:n,configurable:!0})}}function Ze(e,r){{var n=function(){me||(me=!0,h(\"%s: `ref` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)\",r))};n.isReactWarning=!0,Object.defineProperty(e,\"ref\",{get:n,configurable:!0})}}var er=function(e,r,n,a,s,u,i){var o={$$typeof:t,type:e,key:r,ref:n,props:i,_owner:u};return o._store={},Object.defineProperty(o._store,\"validated\",{configurable:!1,enumerable:!1,writable:!0,value:!1}),Object.defineProperty(o,\"_self\",{configurable:!1,enumerable:!1,writable:!1,value:a}),Object.defineProperty(o,\"_source\",{configurable:!1,enumerable:!1,writable:!1,value:s}),Object.freeze&&(Object.freeze(o.props),Object.freeze(o)),o};function rr(e,r,n,a,s){{var u,i={},o=null,m=null;n!==void 0&&(de(n),o=\"\"+n),He(r)&&(de(r.key),o=\"\"+r.key),Xe(r)&&(m=r.ref,Ke(r,s));for(u in r)O.call(r,u)&&!Ge.hasOwnProperty(u)&&(i[u]=r[u]);if(e&&e.defaultProps){var f=e.defaultProps;for(u in f)i[u]===void 0&&(i[u]=f[u])}if(o||m){var d=typeof e==\"function\"?e.displayName||e.name||\"Unknown\":e;o&&Je(i,d),m&&Ze(i,d)}return er(e,o,m,s,a,N.current,i)}}var L=k.ReactCurrentOwner,be=k.ReactDebugCurrentFrame;function w(e){if(e){var r=e._owner,n=C(e.type,e._source,r?r.type:null);be.setExtraStackFrame(n)}else be.setExtraStackFrame(null)}var q;q=!1;function Q(e){return typeof e==\"object\"&&e!==null&&e.$$typeof===t}function ve(){{if(L.current){var e=p(L.current.type);if(e)return`\n\nCheck the render method of \\``+e+\"`.\"}return\"\"}}function nr(e){{if(e!==void 0){var r=e.fileName.replace(/^.*[\\\\\\/]/,\"\"),n=e.lineNumber;return`\n\nCheck your code at `+r+\":\"+n+\".\"}return\"\"}}var pe={};function ar(e){{var r=ve();if(!r){var n=typeof e==\"string\"?e:e.displayName||e.name;n&&(r=`\n\nCheck the top-level render call using <`+n+\">.\")}return r}}function _e(e,r){{if(!e._store||e._store.validated||e.key!=null)return;e._store.validated=!0;var n=ar(r);if(pe[n])return;pe[n]=!0;var a=\"\";e&&e._owner&&e._owner!==L.current&&(a=\" It was passed a child from \"+p(e._owner.type)+\".\"),w(e),h('Each child in a list should have a unique \"key\" prop.%s%s See https://reactjs.org/link/warning-keys for more information.',n,a),w(null)}}function ge(e,r){{if(typeof e!=\"object\")return;if($(e))for(var n=0;n<e.length;n++){var a=e[n];Q(a)&&_e(a,r)}else if(Q(e))e._store&&(e._store.validated=!0);else if(e){var s=Se(e);if(typeof s==\"function\"&&s!==e.entries)for(var u=s.call(e),i;!(i=u.next()).done;)Q(i.value)&&_e(i.value,r)}}}function tr(e){{var r=e.type;if(r==null||typeof r==\"string\")return;var n;if(typeof r==\"function\")n=r.propTypes;else if(typeof r==\"object\"&&(r.$$typeof===T||r.$$typeof===j))n=r.propTypes;else return;if(n){var a=p(r);qe(n,e.props,\"prop\",a,e)}else if(r.PropTypes!==void 0&&!q){q=!0;var s=p(r);h(\"Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?\",s||\"Unknown\")}typeof r.getDefaultProps==\"function\"&&!r.getDefaultProps.isReactClassApproved&&h(\"getDefaultProps is only used on classic React.createClass definitions. Use a static property named `defaultProps` instead.\")}}function or(e){{for(var r=Object.keys(e.props),n=0;n<r.length;n++){var a=r[n];if(a!==\"children\"&&a!==\"key\"){w(e),h(\"Invalid prop `%s` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.\",a),w(null);break}}e.ref!==null&&(w(e),h(\"Invalid attribute `ref` supplied to `React.Fragment`.\"),w(null))}}function ir(e,r,n,a,s,u){{var i=Ie(e);if(!i){var o=\"\";(e===void 0||typeof e==\"object\"&&e!==null&&Object.keys(e).length===0)&&(o+=\" You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.\");var m=nr(s);m?o+=m:o+=ve();var f;e===null?f=\"null\":$(e)?f=\"array\":e!==void 0&&e.$$typeof===t?(f=\"<\"+(p(e.type)||\"Unknown\")+\" />\",o=\" Did you accidentally export a JSX literal instead of a component?\"):f=typeof e,h(\"React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s\",f,o)}var d=rr(e,r,n,s,u);if(d==null)return d;if(i){var b=r.children;if(b!==void 0)if(a)if($(b)){for(var x=0;x<b.length;x++)ge(b[x],e);Object.freeze&&Object.freeze(b)}else h(\"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.\");else ge(b,e)}return e===y?or(d):tr(d),d}}var sr=ir;z.Fragment=y,z.jsxDEV=sr})()});var Ne=B((wr,Re)=>{\"use strict\";Re.exports=xe()});var gr={};hr(gr,{default:()=>_r,frontmatter:()=>vr});var c=mr(Ne()),vr={title:\"QStash\",description:\"QStash is a fully managed serverless queue and messaging service designed for the serverless era.\",date:\"2022-07-18\",url:\"https://upstash.com/qstash\",published:!0};function Te(l){let t=Object.assign({p:\"p\",ul:\"ul\",li:\"li\",a:\"a\"},l.components);return(0,c.jsxDEV)(c.Fragment,{children:[(0,c.jsxDEV)(t.p,{children:\"QStash is an HTTP based messaging and scheduling solution for the serverless and edge runtimes.\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:10,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.ul,{children:[`\n`,(0,c.jsxDEV)(t.li,{children:\"100% serverless, no stateful connections required. Messages are pushed to your API.\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:12,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.li,{children:\"At-least-once delivery guaranteed to any public API\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:13,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.li,{children:\"Pubsub via topics\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:14,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.li,{children:\"Delay message delivery\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:15,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.li,{children:\"Message deduplication\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:16,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.li,{children:\"Scheduling via CRON\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:17,columnNumber:1},this),`\n`]},void 0,!0,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:12,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.p,{children:\"Formally, QStash is a message queue and task scheduler designed for serverless runtimes. Informally, QStash is a glue for your serverless functions.\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:20,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.p,{children:\"There was a perception serverless was only good for simple tasks. Not anymore. People build powerful systems with serverless stack. Powerful systems are composed of multiple components. Communication among those components is a big engineering problem. There are already great solutions for this problem. But we think existing solutions do not fit in serverless space. Either they are too complex or not designed to work with stateless runtimes. So we want a solution which (is):\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:22,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.ul,{children:[`\n`,(0,c.jsxDEV)(t.li,{children:\"Works anywhere including serverless and edge.\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:24,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.li,{children:\"Messaging as a service with no backend for users to run.\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:25,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.li,{children:\"Lightweight, easy to understand, requires nothing to learn.\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:26,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.li,{children:\"Price scales to zero.\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:27,columnNumber:1},this),`\n`]},void 0,!0,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:24,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.p,{children:\"Let's talk about a real world example. We have an e-commerce app and we want to send an informational email after each purchase. We have a service (an API route) for new purchases (newPurchase) and a second service for sending emails and notifications (sendEmail). We can call the sendEmail service from the newPurchase service. But what if the call fails? Should we wait for the response and retry? What if too many calls congest the sendEmail service and the service does not respond on time? You need to handle all these cases in your newPurchase service. Moreover, when you change the contract of sendEmail service; you have to update your newPurchase service too.\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:29,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.p,{children:\"If you use QStash in the above example, you simply send a request to QStash from the newPurchase service. QStash will queue the request and call the sendEmail service. If the service does not respond, QStash will retry with a backoff strategy. The latency of sendEmail service will not affect the newPurchase service, because it will not wait for a response from the sendEmail service. QStash decouples the newPurchase and sendEmail services. You can update both services independently as long as you keep the message format compatible.\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:31,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.p,{children:\"With QStash, you can add delays to the requests. Send an email 3 days after the shipment to remind the customer to add a review. You can also schedule tasks. You can send the requests with a CRON expression, so it will be run repetitively.\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:33,columnNumber:1},this),`\n`,(0,c.jsxDEV)(t.p,{children:[\"To learn more about QStash, visit \",(0,c.jsxDEV)(t.a,{href:\"upstash.com/qstash\",children:\"upstash.com/qstash\"},void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:36,columnNumber:35},this),\".\"]},void 0,!0,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:36,columnNumber:1},this)]},void 0,!0,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\",lineNumber:1,columnNumber:1},this)}function pr(l={}){let{wrapper:t}=l.components||{};return t?(0,c.jsxDEV)(t,Object.assign({},l,{children:(0,c.jsxDEV)(Te,l,void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\"},this)}),void 0,!1,{fileName:\"/Users/andreasthomas/github/chronark/chronark.com/content/projects/_mdx_bundler_entry_point-174140f5-c063-4967-845a-79db15aa866f.mdx\"},this):Te(l)}var _r=pr;return br(gr);})();\n/*! Bundled license information:\n\nreact/cjs/react-jsx-dev-runtime.development.js:\n (**\n * @license React\n * react-jsx-dev-runtime.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *)\n*/\n;return Component;"
|
|
},
|
|
"_id": "projects/qstash.mdx",
|
|
"_raw": {
|
|
"sourceFilePath": "projects/qstash.mdx",
|
|
"sourceFileName": "qstash.mdx",
|
|
"sourceFileDir": "projects",
|
|
"contentType": "mdx",
|
|
"flattenedPath": "projects/qstash"
|
|
},
|
|
"type": "Project",
|
|
"path": "/projects/qstash",
|
|
"slug": "qstash"
|
|
} |