英文:
Mule 4 Object store and caching - store records from Db in cache and then Validate incoming request against them from cache - seems it is possible
问题
感谢@harshank和@aled在我之前的问题这里和这里中的帮助。
这是我无法使其工作的事情,但我的同事却能够,对我来说这没有意义。
所以在这里:
将在下面粘贴整个代码,但将从流程图开始以更好地解释:
这是一个简单的HTTP监听器,用于接收传入请求:HTTP监听器
然后控制流转到一个名为caching_experiment_04
的子流程
缓存实现在这里
这是实际的子流程caching_experiment_04
这个工作方式是通过Postman进行的POST请求:
{
"empId": "E001",
"isActive": true
}
#1 存储原始负载
这里存储了传入的负载,并赋值给变量originalPayload
#2 将硬编码的虚拟负载发送到缓存
在这里,我们实际上是用硬编码的虚拟负载替换了传入的负载(我认为这就像是一种欺骗/愚弄缓存的方法)
%dw 2.0
output application/java
{"dummy": "dummyValue"}
#3 缓存
当代码到达这一点时,第一次缓存中没有任何内容,所以它会进入缓存范围。在这里,我们在模拟数据库检索
中模拟了一个数据库调用来检索数据并将其存储在缓存中。第二次,因为我们将虚拟负载传递给了缓存,我假设缓存会找到相同的负载,并且不会再次进入缓存范围(目前我正在硬编码值为:
%dw 2.0
output application/json
[
{
"empId": "E001",
"isActive": true
},
{
"empId": "E002",
"isActive": false
}
]
所以在这个阶段,上述数据被填充到了缓存中。
#4
现在当控制达到这一点时:检查传入请求是否有效
,我可以在调试模式中看到payload
实际上是缓存中的数据,即模拟的来自数据库的两条记录的数组。
在这里,我正在进行一个简单的业务验证(仅用于说明目的,它是一个检查特定雇员ID和是否激活的简单检查)
问题:
所以以这种欺骗性的方式(每次都将虚拟负载发送到缓存),已经能够使用Mule 4缓存与对象存储进行授权检查。我仍然有些不确定,为什么当我们发出第二个请求,当代码不进入缓存范围时(因为它在缓存中找到了虚拟负载),然后在缓存范围之后,负载不显示虚拟负载,而是显示了来自缓存内部的数据库模拟转换组件的负载。
所以我不能理解为什么传入的虚拟负载被用来确定是否应该进入缓存范围,为什么传入的负载没有被存储在缓存中?
如果传入的虚拟负载没有被存储在缓存中,为什么第二个请求(使用相同的虚拟负载)没有进入缓存?
注意:
在缓存到期之后和/或TTL之前,任何传入请求都将进入缓存范围,并触发数据检索以刷新缓存。
在缓存到期之前和/或TTL之前,任何传入请求都将简单地从缓存中“弹出”(暂时没有更好的词)。
以下是完整的代码:
<http:listener-config name="HTTP_Listener_config" doc:name="HTTP Listener config" doc:id="f1bec56d-de65-4a93-913d-07a7426d6bf6">
<http:listener-connection host="0.0.0.0" port="9091" />
</http:listener-config>
<ee:object-store-caching-strategy name="Caching_Strategy_04" doc:name="Caching Strategy"
doc:id="64214a61-24bc-4231-80b3-b8e11911449d" objectStore="Object_store_04">
</ee:object-store-c
英文:
So thanks to @harshank and to @aled for helping me in my previous questions here and here
So this was something that I was not able to get working but my colleague did and to me it just does not make sense .
So here goes :
Will paste the entire code below - but will start with images of the flow to better explain :
This is a simple HTTP listener which is receiving incoming request : HTTP Listener
then contol goes to a subflow called caching_experiment_04
cachig implementation here
This is the actual subflow caching_experiment_04
So the way this is working is am making a post request via postman :
{
"empId": "E001",
"isActive": true
}
#1 store original payload
Here whatever is the incoming payload is being stored against a variable originalPayload
#2 send hard coded dummy payload to cache
Here we are literally replacing the incoming payload with hard coded dummy payload ( The way I look at it is it is like a hack to trcik / fool the cache )
%dw 2.0
output application/java
---
{"dummy": "dummyValue"}
#3 Cache
When code reaches this point - the first time nothing is present inside the cache so it 'enters' cache scope . Here in simulate db retrieval
as the name states we are simulating a database call to retrieve data and store in cache . The second time around as we are passing the dummay payload to cache - I am assuming cache finds the same payload and does NOT 'enter cache scope' ( For now I am hardcoding values as :
%dw 2.0
output application/json
---
[
{
"empId": "E001",
"isActive": true
},
{
"empId": "E002",
"isActive": false
}
]
So at this stage the above data is populated in cache .
#4
Now when control reaches this point : check if incoming request is valid
I can see in debug mode that the payload
is actually the data that is in cache i.e the mocked array of two records from db .
Here am doing a simple business validation ( for illustration purposes only its a simple check for a specific employee id and if active
Questions:
So in this hacky way ( sending dummy payload to cache everytime ) have been able to use Mule 4 Cache with object store to do an authorisation check . I am still a little unsure why when we make a second request and when code does not enter cache scope ( assuming since it finds the dummy payload in cache ) then why AFTER cache scope the payload does NOT show the dummy payload rather it shows the payload from the db simulated transform component INSIDE the cache.
So I am not able to understand if incoming dummy payload is being used to determine if cache scope should be entered or not why is the incoming payload NOT being stored in cache ?
and if the incoming dummy payload is NOT stored in cache why is the second request ( with same dummy payload NOT entering cache ?
NOTE :
After On cache expiry and/or TTL any incoming request will enter inside cache scope and data retrieval will be triggered to refresh cache
Prior to On cache expiry and /or TTL any incoming request will simply 'bounce' off the cache ( for lack of a better word )
Here is the complete code:
<http:listener-config name="HTTP_Listener_config" doc:name="HTTP Listener config" doc:id="f1bec56d-de65-4a93-913d-07a7426d6bf6" >
<http:listener-connection host="0.0.0.0" port="9091" />
</http:listener-config>
<flow name="caching_experiments" doc:id="1846324d-ea09-4f56-8822-3a4f5f05b123" >
<http:listener doc:name="Listener" doc:id="f1d01332-79c0-4a26-bd1c-1c9639d12168" path="/caching/*" config-ref="HTTP_Listener_config" />
<flow-ref doc:name="caching_experiment_04" doc:id="554cb615-23ca-4f54-869b-622122910bac" name="caching_experiment_04"/>
</flow>
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:os="http://www.mulesoft.org/schema/mule/os" xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/os http://www.mulesoft.org/schema/mule/os/current/mule-os.xsd">
<ee:object-store-caching-strategy name="Caching_Strategy_04" doc:name="Caching Strategy"
doc:id="64214a61-24bc-4231-80b3-b8e11911449d" objectStore="Object_store_04">
</ee:object-store-caching-strategy>
<os:object-store name="Object_store_04" doc:name="Object store" doc:id="cae89912-c583-4061-b684-78def42a1ada"
entryTtl="60" persistent="false" expirationInterval="2"/>
<sub-flow name="caching_experiment_04" doc:id="593c0631-72e7-4692-bee1-5ba4cc1e0363" >
<logger level="INFO" doc:name='"Before cache"' doc:id="83348424-a544-4df6-b0dc-4c2443187998" message="Before cache"/>
<ee:transform doc:name="store original payload" doc:id="54674867-5302-4511-907c-139598cf8f4d" >
<ee:message >
</ee:message>
<ee:variables >
<ee:set-variable variableName="originalPayload" ><![CDATA[%dw 2.0
output application/java
---
payload]]></ee:set-variable>
</ee:variables>
</ee:transform>
<ee:transform doc:name="send hard coded dummy payload to cache" doc:id="ee36fa6a-d4d9-4b53-b041-36c7cc41775d" >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/java
---
{"dummy": "dummyValue"}]]></ee:set-payload>
</ee:message>
</ee:transform>
<ee:cache doc:name="Cache" doc:id="80ea19f7-ca97-4409-a038-34f0c680582b" cachingStrategy-ref="Caching_Strategy_04">
<logger level="INFO" doc:name='call db and retrieve data to be cached' doc:id="5c0815fa-29d3-4657-b74e-bc392e46b9d9" message="call db and retrieve data to be cached" />
<ee:transform doc:name="simulate db retrieval" doc:id="066794e1-4658-41bd-9024-f3e15c145ad4" >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/json
---
[
{
"empId": "E001",
"isActive": true
},
{
"empId": "E002",
"isActive": false
}
]]]></ee:set-payload>
</ee:message>
</ee:transform>
</ee:cache>
<ee:transform doc:name="check if incoming request is valid" doc:id="e1518ccb-87bb-4c4f-ae8d-ff888b0f8dbd" >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/java
---
!isEmpty(payload filter ((item, index) -> item.empId == vars.originalPayload.empId and item.isActive))]]></ee:set-payload>
</ee:message>
<ee:variables >
<ee:set-variable variableName="isValid" ><![CDATA[%dw 2.0
output application/json
---
!isEmpty(payload filter ((item, index) -> item.empId == vars.originalPayload.empId and item.isActive))]]></ee:set-variable>
</ee:variables>
</ee:transform>
<logger level="INFO" doc:name='"After cache"' doc:id="4f70c595-8332-494f-b0af-71517a83e346" message='#["After cache " ++ vars.isValid]'/>
</sub-flow>
</mule>
答案1
得分: 0
缓存范围不缓存接收到的有效负载,而是在执行范围内的Mule组件时生成的有效负载。当传入消息的键与缓存的键匹配时,它会输出缓存的消息信息,而不执行其Mule组件。该范围始终执行,只是决定何时执行包含的组件。由于它使用缓存,您只能通过替换有效负载来确认执行。
请注意,因为您没有定义键生成表达式,它将使用默认值,即输入有效负载的SHA256摘要。由于您只是使用一个固定的虚拟有效负载,这可能不是问题,但在其他情况下应予以注意。
英文:
The Cache Scope doesn't cache the payload that it receives but the payload that it generates when it executes the Mule Components inside the scope. When there is a match between the key of the incoming message and a cached key, it outputs the cached message information and does not execute its Mule Components. The scope always executes, it just decides when it needs to execute the contained components. Since it is using the cache you can only confirm the execution by the replacement of the payload.
Note that because you are not defining a key generation expression, it is using the default which is a SHA256 digest of the input payload. Since you are just using a fixed dummy payload this is not probably an issue, but you should be mindful of it in other scenarios.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论