How do notifications traverse a Puppet resource chain? - puppet

Given this simplified Puppet example, it's clear that any change to my_file will trigger my_service to refresh due to the ~> chaining operator:
package { 'my_package': }
->
file { 'my_file': }
~>
service { 'my_service': }
Will a change to my_package also cause my_service to refresh? (That is, will the state change propagate through a non-notifying -> chain operator?)
I know that refresh events will propagate through a chain if all the operators are notifying operators, but the documentation isn't clear how it works in a mixed chain.

Notifications never propagate through another resource, even if they are in a chain of resources set to notify.
When a resource is "changed", then it notifies any resources subscribed to its own change. Those resources have a refresh method called on them, that does whatever that type requires. After that nothing else happens.
If a notified resource is changed itself, then it will also notify anyone subscribed to it's change. This isn't propagating a notification, it is really propagating changes going through the manifest.
As an example, if /tmp/markerfile already exists this manifest will not apply the exec resource:
notify { 'test': }
~>
file { '/tmp/markerfile':
ensure => present
}
~>
exec { '/bin/date':
refreshonly => true
}

Related

Application Insights Collecting Duplicate Operations

I currently have an Azure ContainerApp architected as a BackgroundService, deployed to Azure. The Worker listens for ServiceBusMessages and processes them.
.NET6
Microsoft.ApplicationInsights.WorkerService 2.21.0
Application Insights is setup like this:
builder.Services.AddApplicationInsightsTelemetryWorkerService(opts =>
{
opts.DependencyCollectionOptions.EnableLegacyCorrelationHeadersInjection = true;
});
builder.Services.ConfigureTelemetryModule<DependencyTrackingTelemetryModule>((module, o) => { module.EnableSqlCommandTextInstrumentation = true; });
and I record the AI Operation in question by injecting a TelemetryClient and using it in the ServiceBusProcessor.ProcessMessageAsync handler like:
using (var op = _telemetryClient.StartOperation<RequestTelemetry>("ProcessAdapterMessage.ProcessSBMessage"))
{
// Process Data
}
My issue is that this operation happens a LOT, which is fine because I use AI sampling, but it's also duplicated. It's recorded once under the proper operation name "ProcessAdapterMessage.ProcessSBMessage", and once under the the operation name "<Empty>".
If I drill down into the "<Empty>" operation, it's actually just "ServiceBusProcessor.ProcessSBMessage" operations that wrap the same method as before. The reason I created the manual op is because looking at data named "Empty" isn't useful, so I'd rather keep my manual op, and make the "Empty" one go away. Any ideas on how to fix this?
This is what the "Empty" Operation details look like
This is what the "ProcessAdapterMessage.ProcessSBMessage" Operation details look like:

Using ZMQ_XPUB_MANUAL with zeromq.js

I am trying to implement a pub/sub broker with ZeroMQ where it is possible to restrict clients from subscribing to prefixes they are not allowed to subscribe to. I found a tutorial that tries to achieve a similar thing using the ZMQ_XPUB_MANUAL option. With zeromq.js it is possible to set this option:
import * as zmq from "zeromq";
// ...
const socket = new zmq.XPublisher({ manual: true });
After setting this option I am able to receive the subscription messages by calling .receive() on this socket:
const [msg] = await socket.receive();
But I have no Idea how to accept this subscription. Usally this is done by calling setSockOpt with ZMQ_SUBSCRIBE but I don't know how to do this with zeromq.js.
Is there a way to call setSockOpt with zeromq.js or is there another way to accept a subscription?
Edit
I tried user3666197's suggestion to call setSockOpt directly, but I am not sure how to do this. Rather than doing that, I took another look in the sources and found this: https://github.com/zeromq/zeromq.js/blob/master/src/native.ts#L617
It seems like setSockOpt is exposed to the TypeScript side as protected methods of the Socket class. To try this out, I created my own class that inherits XPublisher and exposed an acceptSubscription message:
class CustomPublisher extends zmq.XPublisher {
constructor(options?: zmq.SocketOptions<zmq.XPublisher>) {
super(options);
}
public acceptSubscription(subscription: string | null): void {
// ZMQ_SUBSCRIBE has a value of 6
// reference:
// https://github.com/zeromq/libzmq/blob/master/include/zmq.h#L310
this.setStringOption(6, subscription);
}
}
This works like a charm! But do not forget to strip the first byte of the subscription messages, otherwise your client won't receive any messages since the prefix won't match.
Q : "Is there a way to call setSockOpt() with zeromq.js or is there another way to accept a subscription?"
So, let me first mention Somdoron to be, out of doubts & for ages, a master of the ZeroMQ tooling.
Next comes the issue. The GitHub-sources, I was able to review atm, seem to me, that permit the ZMQ_XPUB-Socket-archetypes to process the native API ZMQ_XPUB_MANUAL settings ( re-dressed into manual-property, an idiomatic shift ), yet present no method (so far visible for me) to actually permit user to meet the native API explicit protocol of:
ZMQ_XPUB_MANUAL: change the subscription handling to manual...with manual mode subscription requests are not added to the subscription list. To add subscription the user need to call setsockopt() with ZMQ_SUBSCRIBE on XPUB socket./__ from ZeroMQ native API v.4.3.2 documentation __/
Trying to blind-call the Socket-inherited .SetSockOpt() method may prove me wrong, yet if successful, it may be a way to inject the { ZMQ_SUBSCRIBE | ZMQ_UNSUBSCRIBE } subscription-management steps into the XPUB-instance currently having been switched into the ZMQ_XPUB_MANUAL-mode.
Please test it, and if it fails to work via this super-class inherited method, the shortest remedy would be to claim that collision/conceptual-shortcomings directly to the zeromq.js maintainers ( it might be a W.I.P. item, deeper in their actual v6+ refactoring backlog, so my fingers are crossed for either case ).

Redux/React - Search field is not updating the redux state instantly

I am new to redux world and I am trying to make newspaper app. I am currently working on the search functionality where the user can search for specific newspaper title. The problem is that when I first types eg 'a' the state is ''. And when I type more eg 'b' the state shows that the term is 'a' when it should be 'ab'. I am using redux chrome tools to check this global state.
My Actioncreator is really simple (only returns the term passed to it):
export function search(term) {
return{
type:SEARCH,
term
}
}
Here is the reducer:
const SearchReducer = (state = '', action) => {
switch (action.type) {
case SEARCH:
return action.term;
default:
return state;
}
}
Here is the root reducer:
/*Application state*/
const rootReducer = combineReducers({
weather: WeatherReducer,
filters: FilterReducer,
articles:ArticleReducer,
search: SearchReducer // this should be 'ab', but is 'a'
});
This is really simple setup. Here is how I am communicating with redux.
I have my material-ui textfield (i tried vanilla input field too)
<TextField style={style.searchWidget.search}
floatingLabelText="Search"
value={this.state.term}
onChange={this._onSearchChange}
/>
When the user types something the _onSearchChange func is fired.
_onSearchChange(event) {
this.setState({term: event.target.value});
this.props.search(this.state.term);
}
This will set current state for this search component. Then it will dispatch search action which will update the global state. But does not work correctly. The global state is always 1 step behind.
Any idea?
Edit:
It looks like it is not redux but react. The component state is not updating instantly. Correct term is passed to the actionreducer so it is not redux's fault. I tried to print out this.state.term after setting the state. And it looks like the state is not updating.
This answer adds a bit onto what Aniket Nandan pointed out -- you are using setState inside of your React component instead of relying on props from above.
The main purpose of using Redux is to take your state and put it in a container alongside the application. The benefit in doing so is that your state can be shared across multiple components and you can then pass things via props into the components in your component tree.
The use of a state container (which has always reminded me a bit of using state machines) allows you to build your application without the complication of having to hand callbacks down through the tree to get changes to go back up to the top. Instead, Redux handles the changes to state and hands everything back off to React through props.
_onSearchChange(event) {
this.setState({term: event.target.value});
this.props.search(this.state.term);
}
On that note, looking at the code above, from your post, I am wondering why you setState to the term, but then always call a function you received through props? Does the search then call up to the dispatch method from the Redux store? If not, then you are not quite wired up correctly.
Further to that point, if you used connect correctly (from react-redux), then you should have the dispatch method from the Redux store available (this happens through context).
The way Redux is designed to work is something more like this:
_onSearchChange(event) {
this.props.dispatch({ type: 'SEARCH', term: event.target.value });
}
What would then happen is Redux should handle the state updates, and the new state will flow from Redux to React via props (this happens through all the connections under the hood in Redux, which is pretty awesome!).
const SearchReducer = (state = '', action) => {
switch (action.type) {
case SEARCH:
return action.term;
break;
default:
return state;
}
}
Based on your reducer (copied above ^^) and your use of combineReducers, you should end up with a state that has { search: { term: 'ab' } } if you typed 'ab', and it should be 'a' after typing only 'a', rather than lagging behind.
What was actually happening with your use of setState and the method coming from props was the initial state (I'm assuming '') was being passed to this.props.search, the first time. Meanwhile, state was updating on the component to be 'a' after you typed 'a'. Then, the next time, when you typed 'b', the state was updating to 'ab', but this.props.search was only receiving the term from state before the setState finished executing -- while it was still 'a'.
This is actually one of the reasons why Redux is so awesome -- it provides a way to ensure that state is updated properly based on user actions within its own container, so that you can guarantee things are in sync across your application.
On that note, I will leave a piece of advice for working with Redux: You should rarely find yourself using setState within a React component that is in an application using Redux. The decision of when to use setState within a component should hinge on whether the piece of state you want to set only exists within that component and the rest of the application does not need to know about it. I cannot think of an example, and any I could offer would probably be quite contrived. To that point, the reason I can't think of one is because I think it is quite a rarity that you would have such a use case in an application.
So, you should be sticking to only using the dispatch method from the Redux store and allowing Redux to handle the state updates through its workflow and allow state to flow downward through props to the components. Adhering to this flow will prevent a lot of these weird "states getting out of sync" types of issues that can happen.
Actually it is not related to redux. You'll have to remember while working with react that you can not get the updated state as soon as you update your react state. let's take an example.
getInitialState: function() {
return {
myState: 0
}
},
updateState: function(stateVersion) {
console.log(this.state.myState); //this will print 0
this.setState({ myState: stateVersion });
console.log(this.state.myState); //this will print 0
}
now for the first time if we call updateState function with state version as argument it will print 0 for both the console even if we sent 1 or 2 or any number as argument.
suppose we have sent 2 as argument. then we can get that state in the next call of that function with another arguments.
But react also take care of this.
You may think that if the state is not updated as soon as we update that then how can I work with that. But react is a good boy...
if you call a function to update a state and next you call another function to work with last updated state then you can work with that.
I think I have already answered your question that why not redux state is updated.
another think is that when you are using redux state for your search reducer then why you are also handling react state. you can directly pass the searched params into your action. You can get that update instantly from your reducer state.
It will help your code simplicity.
I found the solution.
React - State not updated
It appears that the setState is actually not instantly setting the state.
So I used a callback function instead.
_onSearchChange(event) {
this.setState({term: event.target.value}, function () {
console.log(this.state.term)
});
}
Now when I type 'a' it will log 'a'!

Have puppet ensure a service is running only when not in a maintenance mode

I have a basic service check in a puppet manifest I want running most of the time with just
service{ $service_name :
ensure => "running",
enable => "true",
}
The thing is there are periods of maintenance I would like to ensure puppet doesn't come along and try to start it back up.
I was thinking creating a file "no_service_start" in a specified path and do a 'creates' check like you could do with a guard for exec but it doesn't look like that's available for the service type.
My next thought was to have the actual service init script do the check for this file itself and just die early if that guard file exists.
While this works in that it prevents a service from starting it manifests itself as a big red error in puppet (as expected). Given the service not starting is a desired outcome if that file is in place I'd rather not have an error message present and have to spend time thinking about if it's "legit" or not.
Is there a more "puppet" way this should be implemented though?
Define a fact for when maintenance is happening.
Then put the service definition in an if block based off that fact.
if !maintenance
{
service{ $service_name :
ensure => "running",
enable => "true",
}
}
Then when puppet compiles the catalog if maintenance == true the service will not be managed and stay in whatever state it currently happens to be.
I don't really like this answer, but to work around puppet spitting out errors when bailing b/c of a guard file is to have to init script that's doing that check bail with an exit code as 0.
How about putting the check outside? You could do something similar to this: https://stackoverflow.com/a/20552751/1097483, except with your service check inside the if loop.
As xiankai said, you can do this on the puppetmaster. If you have a script that returns running or stopped as a string, depending on the current time or anything, you can write something like:
service{ $service_name :
ensure => generate('/usr/local/bin/maintenanceScript.sh');
}

Fault Tolerance & state management in Domain Services

In my domain, services are used to coordinate higher level behavior that involve multiple aggregates and/or other services. Take for instance an order management system which needs to perform the following steps when canceling an order:
Change the state of the Order to "Canceled"
Reverse any pending credit card transaction
Add an audit entry containing an explanation why the order was canceled
Persist changes to the Order to the data store
Raise the OrderCanceledEvent (as a message)
Coding this is pretty straight-forward except there are a few additional concerns I have to implement:
I cannot perform any of the actions if the Order is not in a
"cancelable" state
I cannot perform any of the actions if the current user does not have
permission to cancel orders
If I cannot reverse the credit card transaction then the entire
operation should fail and the Order should remain in its original
state
Failing to add the audit entry does not abort the operation
Failing to persist the Order should abort the operation and the Order
should remain in its original state
The operation is only successful if steps 1, 2, and 4 succeed. As a result, I cannot have these steps implemented as event handlers.
Putting aside any issues with the persistance mechanism in use (it is what it is), can you help me understand how best to implement my service so that it handles validation, errors and managing the state of the Order properly?
(I should note that I am not using Event Sourcing, so don't let the OrderCanceledEvent throw you.)
One way to solve this with event handlers is with the use of a saga. The workflow would be as follows:
Upon receiving CancelOrder command, a OrderCancellationSaga is started, placing the order into a Cancelling state.
Upon confirmation of refund from payment gateway, the saga is completed and the order is placed into a cancelled state and persisted. At this point, within the same transaction, the OrderCancelled event is raised.
If the interaction with the payment gateway fails or is declined, the order can be reverted into the prior state or placed into some sort of error state.
In this scenario auditing can occur at any stage. Also, permissions and whether the order can be cancelled in the first place should be verified before starting the saga or as a first step in starting the saga.
Rough sample with C# and NServiceBus sagas:
class OrderOrderCancellationSaga : Saga<OrderCancellationSagaData>
,IAmStartedBy<CancelOrderCommand>,
,IHandle<PaymentGatewayInteractionFailedEvent>
{
public OrderService OrderService { get; set; }
public PaymentGateway PaymentGateway { get; set; }
// correlate saga messages by order ID
public override void ConfigureHowToFindSaga()
{
ConfigureMapping<PaymentGatewayInteractionFailedEvent>(x => x.OrderId, x =>x.OrderId);
ConfigureMapping<RefundCompletedEvent>(x => x.OrderId, x => x.OrderId);
}
// start cancellation process
public void Handle(CancelOrderCommand message)
{
// check if cancellation is authorized and valid
// ....
// can save prior state here, if needed
this.Data.OrderId = message.OrderId;
this.Data.State = "Cancelling";
this.Bus.Send(new RefundOrderCommand(...));
}
public void Handle(RefundCompletedEvent message)
{
this.Data.State = "Cancelled";
this.OrderService.CompleteCancellation(...);
MarkAsComplete();
}
// this handler can be hosted on a different endpoint.
public void Handle(RefundOrderCommand message)
{
try
{
this.PaymentGateway.Refund(...
}
catch(Exception ex)
{
this.Bus.Reply(new PaymentGatewayInteractionFailedEventmessage(...));
}
}
// this handler can be used to revert whole operation.
public void Handle(PaymentGatewayInteractionFailedEvent message)
{
// or revert to prior state.
this.Data.Status = "Cancellation Failed";
// call any application services needed.
// finishes saga, deleting state
MarkAsComplete();
}
}

Resources