I am am struggling how to define a state change where one event can be posted per step but multiple removed. I have this model:
open util/ordering[State]
sig Event {}
sig State {
queue : set Event
}
pred State.post( next' : State, event : Event ) {
next'.queue = this.queue + event
}
pred State.deliver( next' : State ) {
next'.queue = this.queue - this.queue // STRUGGLE!
}
fact traces {
no first.queue
all s : State - last, next : s.next {
some e : Event | s.post[next,e] or s.deliver[next]
}
}
However, I want to model that in the deliver step I deliver some events by removing them. In the code I deliver all but how do I code it that it will actually try any subset of this.queue?
It seems the struggle come from the fact you try to write this predicate as an assignment.
The solution becomes clear when adopting a more declarative view on the problem. It is simply needed to enforce that the new queue be a proper subset of the previous queue:
pred State.deliver( next' : State ) {
next'.queue in this.queue and next'.queue != this.queue
}
Related
I'm trying to visualise a spec for a Payment object where it moves from "queued" to "processing" to "complete". I have come up with the following:
enum State {Queued, Processing, Complete}
sig Payment {
var state: State
}
pred processPayment[p: Payment] {
p.state = Queued // guard
p.state' = Processing // action
}
pred completePayment[p: Payment] {
p.state = Processing // guard
p.state' = Complete // action
}
fact init {
Payment.state = Queued
}
fact next {
always (some p : Payment | processPayment[p] or completePayment[p])
}
run {} for 1 Payment
Unfortunately, I get no instances found for this spec. From my understanding, a Payment with state "Queued" initially and a next state where it's in "Processing" should be allowed with the always (some p : Payment | processPayment[p] or completePayment[p])" formula according to the tutorial at https://haslab.github.io/formal-software-design/overview/index.html. Am I missing something?
The issue turned out to be a missing terminating predicate, adding the below(or a stutter) fixes it.
pred afterComplete[p: Payment] {
p.state = Complete // guard
p.state' = Complete // action
}
I am not an expert but I believe that it is impossible for either of your predicates to be true at t0. I think you need a holdPayment predicate like this:
pred holdPayment[p:Payment] {
p.state = p.state'
}
fact next {
always (some p : Payment | processPayment[p] or completePayment[p] or holdPayment[p])
}
run {} for 1 Payment
TL;DR
I want to delay a publication, but can't figure out how to, er, combine the parts
In Brief
I have a Publisher
let generator = PassthroughSubject<Bool, Never>()
and want somehow to use the modifier
.delay(for: 2, scheduler: RunLoop.main)
so that when I call
generator.send(true)
the message is sent two seconds after the call to send()
Looking at the docs for Publishers.Delay made the type error more clear, but doesn't help me to find the right way to hook things up.
Code
import SwiftUI
import Combine
// Exists just to subscribe.
struct ContainedView : View {
private let publisher: AnyPublisher<Bool, Never>
init(_ publisher: AnyPublisher<Bool, Never> = Just(false).dropFirst().eraseToAnyPublisher()) {
self.publisher = publisher
}
var body: some View {
Rectangle().onReceive(publisher) { _ in print("Got it") }
}
}
struct ContentView: View {
let generator = PassthroughSubject<Bool, Never>()
// .delay(for: 2, scheduler: RunLoop.main)
// Putting it here doesn't work either.
var body: some View {
VStack {
Button("Tap") {
// Does not compile
self.generator.delay(for: 2, scheduler: RunLoop.main).send(true)
// Value of type 'Publishers.Delay<PassthroughSubject<Bool, Never>, RunLoop>' has no member 'send'
// https://developer.apple.com/documentation/combine/publishers/delay
// Does not compile
self.generator.send(true).delay(for: 2, scheduler: RunLoop.main)
// Value of tuple type '()' has no member 'delay'
// Just a broken-up version of the first try.
let delayed = self.generator.delay(for: 2, scheduler: RunLoop.main)
delayed.send(true)
// This, of course, builds and works.
self.generator.send(true)
print("Sent it")
}
ContainedView(generator.eraseToAnyPublisher())
.frame(width: 300, height: 200)
}
}
}
You can use the debounce property of a publisher to delay the publishing.
$yourProperty
.debounce(for: 0.8, scheduler: RunLoop.main)
.eraseToAnyPublisher()
.delay(for: 2, scheduler: RunLoop.main) is likely exactly what you need, but it'll be key to see how you're subscribing to fully understand the issue. Delay doesn't delay the sending of the value when using send() with a subject - that's a link for imperative code and sends the data whenever send is invoked, typically against some already existing subscription.
While you have a subscriber in the first bit of code, there isn't one with the subject to pin these together.
For example, if you updated:
Just(false).dropFirst().eraseToAnyPublisher()
to
Just(false).dropFirst().eraseToAnyPublisher().delay(for: 2, scheduler: RunLoop.main)
Then the print statement should trigger ~2 second after the the init() was invoked. Depending on what you're trying to accomplish here, using a closure trigger such as onAppear might make a lot more sense, having that call the subject.send(), which you can then delay as you like in the publisher chain that happens before whatever subscribes to it.
var cancellables: [AnyCancellable] = []
let generator = PassthroughSubject<Bool, Never>()
let generated = generator.delay(for: 2, scheduler: RunLoop.main).sink { value in
print(value.description + " " + Date().timeIntervalSinceReferenceDate.description)
}
print(Date().timeIntervalSinceReferenceDate.description)
generator.send(true)
generator.send(false)
output
641453284.840604
true 641453286.841731
false 641453286.847715
What's the function of DynamicFilters in PrestoSql DistributedExecutionPlanner.Visitor?
private Map<PlanNodeId, SplitSource> visitScanAndFilter(TableScanNode node, Optional<FilterNode> filter)
{
// ***What's the purpose of dynamicFilters and how to use it?***
List<DynamicFilters.Descriptor> dynamicFilters = filter
.map(FilterNode::getPredicate)
.map(expression -> extractDynamicFilters(metadata, expression))
.map(DynamicFilters.ExtractResult::getDynamicConjuncts)
.orElse(ImmutableList.of());
// TODO: Execution must be plugged in here
if (!dynamicFilters.isEmpty()) {
log.debug("Dynamic filters: %s", dynamicFilters);
}
// get dataSource for table
SplitSource splitSource = splitManager.getSplits(
session,
node.getTable(),
stageExecutionDescriptor.isScanGroupedExecution(node.getId()) ? GROUPED_SCHEDULING : UNGROUPED_SCHEDULING);
splitSources.add(splitSource);
return ImmutableMap.of(node.getId(), splitSource);
}
As Martin suggested, https://trino.io/blog/2019/06/30/dynamic-filtering.html describes the meaning of dynamic filters.
The TODOs in the code are there because not every part of this functionality is implemented yet. You can track https://github.com/trino/presto/issues/52
After reading the docs on ServerValue.TIMESTAMP, I was under the impression that once the object hits the database, the timestamp placeholder evaluates once and remains the same, but this was not the case for me:
// Example on Node:
> const db = f.FIREBASE_APP.database();
> const timestamp = f.FIREBASE_APP.database.ServerValue.TIMESTAMP;
> const ref = db.ref('/test');
> ref.on(
... 'child_added',
... function(snapshot) {
..... console.log(`Timestamp from listener: ${snapshot.val().timestamp}`);
..... }
... )
> var child_key = "";
> ref.push({timestamp: timestamp}).then(
... function(thenable_ref) {
..... child_key = thenable_ref.key;
..... }
... );
Timestamp from listener: 1534373384299
> ref.child(child_key).once('value').then(
... function(snapshot) {
..... console.log(`Timestamp after querying: ${snapshot.val().timestamp}`);
..... }
... );
> Timestamp after querying: 1534373384381
> 1534373384299 < 1534373384381
true
The timestamp is different when queried from the on listener and it is different during a later query.
Is this like this by design and I just missed some parts of the documentation? If this is the case, when does the ServerValue.TIMESTAMP stabilize?
I am building a CQRS/ES library on the Realtime Database, and just wanted to avoid the expected_version (or sequence numbers) of events.
UPDATE
The proof for Frank's explanation below:
/* `db`, `ref` and `timestamp` are defined above,
and the test path ("/test") has been deleted
from DB beforehand to avoid noise.
*/
> ref.on(
... 'child_added',
... function(snapshot) {
..... console.log(`Timestamp from listener: ${snapshot.val().timestamp}`);
..... }
... )
> ref.on(
... 'value',
... function(snapshot) {
..... console.log(snapshot.val());
..... }
... )
> ref.push({timestamp: timestamp}); null;
Timestamp from listener: 1534434409034
{ '-LK2Pjd8FS_L8hKqIpiE': { timestamp: 1534434409034 } }
{ '-LK2Pjd8FS_L8hKqIpiE': { timestamp: 1534434409114 } }
Bottom line is, if one needs to rely on immutable server side timestamps, keep this in mind, or work around it.
When you perform the ref.push({timestamp: timestamp}) the Firebase client immediately makes an estimate of the timestamp on the client and fires an event for that locally. It then send the command off to the server.
Once the Firebase client receives the response from the server, it checks if the actual timestamp is different from its estimate. If it is indeed different, the client fires reconciliatory events.
You can most easily see this by attaching your value listener before setting the value. You'll see it fire with both the initial estimates value, and the final value from the server.
Also see:
How to use the Firebase server timestamp to generate date created?
Trying to convert Firebase timestamp to NSDate in Swift
firebase.database.ServerValue.TIMESTAMP return an Object
CAVEAT: After wasting another day, the ultimate solution is not to use Firebase server timestamps at all, if you have to compare them in a use case that is similar to the one below. When the events come in fast enough, the second 'value' update may not trigger at all.
One solution, to the double-update condition Frank describes in his answer, is to get the final server timestamp value is (1) to embed an on('event', ...) listener inside an on('child_added', ...) and (2) remove the on('event', ...) listener as soon as the specific use case permits.
> const db = f.FIREBASE_APP.database();
> const ref = db.ref('/test');
> const timestamp = f.FIREBASE_APP.database.ServerValue.TIMESTAMP;
> ref.on(
'child_added',
function(child_snapshot) {
console.log(`Timestamp in 'child_added': ${child_snapshot.val().timestamp}`);
ref.child(child_snapshot.key).on(
'value',
function(child_value_snapshot) {
// Do a timestamp comparison here and remove `on('value',...)`
// listener here, but keep in mind:
// + it will fire TWICE when new child is added
// + but only ONCE for previously added children!
console.log(`Timestamp in embedded 'event': ${child_value_snapshot.val().timestamp}`);
}
)
}
)
// One child was already in the bank, when above code was invoked:
Timestamp in 'child_added': 1534530688785
Timestamp in embedded 'event': 1534530688785
// Adding a new event:
> ref.push({timestamp: timestamp});null;
Timestamp in 'child_added': 1534530867511
Timestamp in embedded 'event': 1534530867511
Timestamp in embedded 'event': 1534530867606
In my CQRS/ES case, events get written into the "/event_store" path, and the 'child_added' listener updates the cumulated state whenever new events come in, where each event has a ServerValue.TIMESTAMP. The listener compares the new event's and the state's timestamp whether the new event should be applied or it already has been (this mostly matters when the server has been restarted to build the internal in-memory state). Link to the full implementation, but here's a shortened outline on how single/double firing has been handled:
event_store.on(
'child_added',
function(event_snapshot) {
const event_ref = event_store.child(event_id)
event_ref.on(
'value',
function(event_value_snapshot){
const event_timestamp = event_value_snapshot.val().timestamp;
if ( event_timestamp <= state_timestamp ) {
// === 1 =======
event_ref.off();
// =============
} else {
var next_state = {};
if ( event_id === state.latest_event_id ) {
next_state["timestamp"] = event_timestamp;
Object.assign(state, next_state);
db.ref("/state").child(stream_id).update(state);
// === 2 =======
event_ref.off();
// =============
} else {
next_state = event_handler(event_snapshot, state);
next_state["latest_event_id"] = event_id;
Object.assign(state, next_state);
}
}
}
);
}
);
When the server is restarted, on('child_added', ...) goes through all events already in the "/event_store", attaching on('value',...) dynamically on all children and compares the events` timestamps to the current state's.
If the event is older than the age of the current state (event_timestamp < state_timestamp is true), the only action is detaching the 'value' listener . This callback will be fired once as the ServerValue.TIMESTAMP placeholder has already been resolved once in the past.
Otherwise the event is newer, which means that it hasn't been applied yet to the current state and ServerValue.TIMESTAMP also hasn't been evaluated yet, causing the callback to fire twice. To handle the double update, this block saves the actual child's key (i.e., event_id here) to the state (to latest_event_id) and compares it to the incoming event's key (i.e., event_id):
While answering a question I attempted to implement a setup where the main thread joins the efforts of the CommonPool to execute a number of independent tasks in parallel (this is how java.util.streams operates).
I create as many actors as there are CommonPool threads, plus a channel for the main thread. The actors use rendezvous channels:
val resultChannel = Channel<Double>(UNLIMITED)
val poolComputeChannels = (1..commonPool().parallelism).map {
actor<Task>(CommonPool) {
for (task in channel) {
task.execute().also { resultChannel.send(it) }
}
}
}
val mainComputeChannel = Channel<Task>()
val allComputeChannels = poolComputeChannels + mainComputeChannel
This allows me to distribute the load by using a select expression to find an idle actor for each task:
select {
allComputeChannels.forEach { chan ->
chan.onSend(task) {}
}
}
So I send all the tasks and close the channels:
launch(CommonPool) {
jobs.forEach { task ->
select {
allComputeChannels.forEach { chan ->
chan.onSend(task) {}
}
}
}
allComputeChannels.forEach { it.close() }
}
Now I have to write the code for the main thread. Here I decided to serve both the mainComputeChannel, executing the tasks submitted to the main thread, and the resultChannel, accumulating the individual results into the final sum:
return runBlocking {
var completedCount = 0
var sum = 0.0
while (completedCount < NUM_TASKS) {
select<Unit> {
mainComputeChannel.onReceive { task ->
task.execute().also { resultChannel.send(it) }
}
resultChannel.onReceive { result ->
sum += result
completedCount++
}
}
}
resultChannel.close()
sum
}
This gives rise to the situation where mainComputeChannel may be closed from a CommonPool thread, but the resultChannel still needs serving. If the channel is closed, onReceive will throw an exception and onReceiveOrNull will immediately select with null. Neither option is acceptable. I didn't find a way to avoid registering the mainComputeChannel if it's closed, either. If I use if (!mainComputeChannel.isClosedForReceive), it will not be atomic with the registration call.
This leads me to my question: what would be a good idiom to select over channels where some may get closed by another thread while others are still live?
The kotlinx.coroutines library is currently missing a primitive to make it convenient. The outstanding proposal is to add receiveOrClose function and onReceiveOrClosed clause for select that would make writing code like this possible.
However, you will still have to manually track the fact that your mainComputeChannel was closed and stop selecting on it when it was. So, using a proposed onReceiveOrClosed clause you'll write something like this:
// outside of loop
var mainComputeChannelClosed = false
// inside loop
select<Unit> {
if (!mainComputeChannelClosed) {
mainComputeChannel.onReceiveOrClosed {
if (it.isClosed) mainComputeChannelClosed = true
else { /* do something with it */ }
}
}
// more clauses
}
See https://github.com/Kotlin/kotlinx.coroutines/issues/330 for details.
There are no proposals on the table to further simplify this kind of pattern.