Skip to content

Latest commit

 

History

History
1160 lines (873 loc) · 74.6 KB

2023-01-12.md

File metadata and controls

1160 lines (873 loc) · 74.6 KB

< 2023-01-12 >

there were a lot of events recorded by gharchive.org of which 2,245,633 were push events containing 3,351,247 commit messages that amount to 255,458,495 characters filtered with words.py@e23d022007... to these 23 messages:

Thursday 2023-01-12 00:38:32 by willior

integrate Cast animations into AnimationTree

when we cast a Formula, it is the Formula script that tells the player which animation to play. a Cast is split into two animations: Cast_Start and Cast_End (previously named Cast_1 & Cast_2). previously, to do this, we'd disable the player's AnimationTree in order to play the Cast animations directly on the Player's AnimationPlayer - since if an AnimationPlayer is part of an AnimationTree, its methods get disabled and instead its playback is controlled via the AnimationTree it's a part of. i always thought this was a finnicky and brittle system: we basically have this big AnimationTree/StateMachine to handle transitions between animations, but then disable it to play these two animations (Cast_1 & Cast_2), then re-enable it via player.action_finished(), which is called at the end of the Cast_2 animation. it doesn't make much sense. luckily, i've learned of the animationState.start() function, which plays an AnimationNode the moment it's called, regardless of if there is a transition to the AnimationNode in the AnimationStateMachine or not. which is... super fucking useful and i didn't know such a method existed before. there are a few other instances where i do the same thing, so i need to make sure the systems are all synchronized and working well with each other. so now, the base Formula class calls player.animationState.start("Cast_Start") when its start() method is called (which is done when a formula cast is confirmed via the FormulaTargetScreen). this starts the animation. it also calls player.action_start(), which handles certain behaviour: it pauses the charge if there is one; it disables player interaction; and it sets the ACTION state, preventing the handling of input events. Formulas have their own AnimationPlayer to specify event times, eg. when to instantiate effects and when to end the cast. typically, formulas will conclude by calling their "ability_end()" method, which now calls player.animationState.start("Cast_End"), the 2nd half of the full casting animation. at the end of the Cast_End animation, we call action_finished(), which resets the changes made by action_start(): it re-enables player interaction; it resumes the charge if the attack button is pressed (or resets the charge if it's not); and it sets the player stat to MOVE. in addition, it checks for a Stun node. this is because Players cannot be interrupted out of casting, even by the Stun status (though maybe this should change... we'll see). when a Stun node is placed onto a Player, it calls the player's "start_stun()" method, which reset & stops the charge, calls reset_action_stat_modifiers(), and calls clear_queued_actions(). then it checks if state == ACTION, and if it is (such as when casting), it forgoes running the final 2 lines of code, which set the state = STUN and tells the animationState.travel("Stun"). this is what prevents the casting animation from being interrupted, as well as prevents the player state from switching from ACTION to STUN during the casting animation. so, if a Player does incur Stun while casting, what happens when we check for the Stun node and find one (player.action_finished()) is we immediately set the state to STUN, and call animationState.travel("Stun"), which are the two start_stun() operations that were skipped if a Stun was incurred while casting (aka while in the ACTION state). so the Stun is there, it works, it has the proper duration (and i believe you should even be able to begin mashing out of it before the casting is complete and action_finished() is called); Stun simply allows the casting animation & state to finish before assuming its full functionality. also added a new player flag, stun_bounce. the purpose of this boolean is to determine whether an attack versus an armored enemy that bounces results in stunning the player or not. right now, the only attack that sets stun_bounce to true is Shadow Strike. stun_bounce becomes false when reset_action_stat_modifiers() is called, which is a method used to revert a player's action modifiers to default (eg. backsteps and rolling bestow an evasion action bonus, which is reset on reset_action_stat_modifiers(), among other things). reset_action_stat_modifiers() is called:

  1. on _ready();
  2. on attack_animation_finished();
  3. on evade_action_finished();
  4. _on_Hurtbox_area_entered() if player_staggered == true; and
  5. on start_stun().

i believe this accounts for all the situations in which action stat modifiers (which are stat modifiers associated with particular actions, such as techs & evasions) require resetting. if you roll, for example, reset_action_stat_modifiers() is called either when the roll animation completes, if you get staggered (hit for more than 10% of your max HP), or if you get stunned. if you attack, for example, reset_action_stat_modifiers() is called either when the attack animation completes, upon getting staggered, or stunned. it works alright but i remember there being moments where an evasion action bonus wasn't reset to 0 following evasion of an attack while rolling, resulting in a much higher than intended evasion value until the next time reset_action_stat_modifiers() is called. i have a theory why this is occurring, and a potential fix. the fix is actually intended to solve a different issue, but it should end up solving this one too. the issue i'm referring to is one where if an enemy attack is successfully evaded, their hitbox remains active and can continue to be monitored by the hurtbox. a somewhat fucky solution would be simply to disable the enemy hurtbox if an attack was evaded, but this would mean that during multiplayer, if one player successfully evades an attack, the attack is effectively nullified for all players if the evading player's hurtbox was the first to register the hit. i guess another fucky solution would be to give temporary invincibility to the player; disable the hitbox. but no, i don't like that either. might have to do what we've done for enemies' hurtboxes, which is...

EnemyHurtbox.gd func start_invincibility(duration, damage_source): self.invincible = true hitboxes.push_back(damage_source) var new_timer = Timer.new() new_timer.one_shot = true new_timer.connect("timeout",Callable(self,"_on_Timer_timeout")) add_child(new_timer) new_timer.start(duration)

func _on_Timer_timeout(): hitboxes.remove_at(0) get_child(1).queue_free() if hitboxes.size() == 0: self.invincible = false

Enemy_Class.gd func hurtbox_entered(): for h in hurtboxes.size(): if hurtboxes[h].invincible: if hurtboxes[h].hitboxes.has(damage_source): return [null, null, null]

i won't go through all this code in detail, but basically it makes it so that enemies can only be hit once per hitbox each second. it can still be hit by multiple hitboxes: just not the same one in a 1 second span. the only way for an enemy to be hit more than once by the same hitbox is if the hitbox lingers for more than 1s. i'm going to implement this feature for the player next, if i can't think of any reasons not to.


Thursday 2023-01-12 00:55:12 by Adam Beigel

feat: simulate images

feat: upload PictureCreation folder and rename

defined a bunch of variables and made the script for circles

target generator is done

I pulled an all-nighter for this... just to make fucking pictures

leftover

fixed a couple of things

new master images* (the files are too big)

the thing is that we are dealing with a 1GB photo and most likely will take a while to generate all the background images using flip image augmentation

Im going insane

for some reason whenever I try to use opencv's bounding box it always throws this error: cv2.error: OpenCV(4.6.0) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\convhull.cpp:143: error: (-215:Assertion failed) total >= 0 && (depth == CV_32F || depth == CV_32S) in function 'cv::convexHull'

IDK what this means and its 2 am and I just want this to work

final a some what working script

whats left: figure out how to get a more accurate bounding box, how to crop a rotated rectangle

updated ignores

finally creates the images with all features

but the image of the picture is bad quality due to all the rotating so im going to rewrite it. Also, the coordinates for the bounding box is not right for some reason.

alright the valid camera image generation

basically fixed the transformations

end of me testing stuff

All I have done testenv has like what the script really should be.

changed some coords

ayo no rotation it works so far

It works. It accurately represents the runway

finally finished ( to use import pain and run fnl_valid_gen)

cleaning the branch up and switched to jpgs bc smaller

added a test

initial exploration and math

i am god

check if target in snapshot

data saving done

change imports and use of var

curse you advik the platypus!!!!!!!!!

I rewrote the whole thing again

fix some file logic

ran some tests and entered stats

word and decimal points

remove notebook


Thursday 2023-01-12 02:03:42 by Marco Antonio Jaguaribe Costa

Add a CMake build option

Tried to stay as close as possible to ja2_2019.sln, has a bunch of ugly hacks due to how much the build relies on preprocessor definitions to define what is being built, which means changing between languages, from Ja2 1.12 to UB or toggling editor means you have to rebuild everything.

This is why I used add_library(x INTERFACE ...) and target_sources(x INTERFACE ...) instead of the default STATIC or SHARED library targets. It's just the least awful way to make sure the preprocessor definitions get to where they need to be.

Below shows how the -DLanguages -DApplications switches work, If you don't set them, the CMakeCache.txt of them will be set to ENGLISH and Ja2, respectively

For Visual Studio 2022 there's a plug and play RelWithDebInfo Ja2 ENGLISH executable, and a CMakeUserPresets_VS2022.json template file

cmake [...] // nothing set, configure just JA2_ENGLISH.exe by default cmake [...] -DApplications="JA2UB" // configures just Unfinished Business cmake [...] build -DApplications="JA2UB;JA2UBMAPEDITOR" // Unfinished Business and UB Map Editor cmake [...] build -DApplications="JA2UB;JA2MAPEDITOR;ALL" // ALL is in the list, configures every application cmake [...] build -DApplications="JA2MAPEDITOR;DeathStranding" // fatal error: DeathStranding not an application

cmake [...] -DLanguages="GERMAN" // configures just German targets cmake [...] build -DLanguages="GERMAN;ENGLISH" // German and English cmake [...] build -DLanguages="GERMAN;ENGLISH;ALL" // ALL is in the list, configures every language cmake [...] build -DLanguages="ENGLISH;ESPERANTO" // fatal error: ESPERANTO not supported


Thursday 2023-01-12 02:37:19 by willior

clear_queued_actions() functioning properly

i haven't been able to re-create the player freeze bug, but i have a feeling it had to do with a tech being queued but not starting after a roll. when tech_queued = true when evade_animation_finished() is called, clear_queued_actions() is called when check_weapon_charge() is called - jesus, that's a mouthful. i'm trying to make sure our queued flags get reset properly, every time, as well as our action stat modifiers. i'm not sure what else could be causing this... the player gets stuck in the ROLL state, on the final frame of the roll animation. i've even had this bug occur the moment the roll action is pressed: no animation plays, though the roll state is set, and then... nothing. in a desperate attempt to fix this, i've made it so the roll_animation_complete() method is called at the same time as the end of the animation. i've also changed the method call mode from "deferred" to "immediate" - maybe, since method calls were deferred, some other method was being called on the same frame first which fucked with the animation, somehow... i have no fucking idea... after some rigourous testing, it seems the bug occurs when a roll STARTS - or rather, when it's supposed to start - as opposed to when it's supposed to finish. my theory is that state gets set to MOVE, and so we begin listening for "roll" inputs; roll input gets handled, but the Animation system still thinks we're on the previous Roll animation, so nothing happens. my workaround is to call AnimationState.start("Roll") as opposed to AnimationState.travel - same as we do for backstep. it seems to work, but this bug is very intermittent and difficult to test for. all of this rolling makes me want to implement a new mechanic where you can chain rolls one after the other if you have good timing. i'll do that next.


Thursday 2023-01-12 02:40:33 by Jose Millnitz

made it in go a while a"go"

sorry for the little joke, i, somehow, messed up the repository with force (worst experience of my life) just reposting the "go"de


Thursday 2023-01-12 03:15:23 by Daggersoath

Added series missing when searching with Japanese titles (#66)

  • Added series with Japanese titles Added Japanese titles to synonyms for preexisting series
  • I'm standing on a million lives
  • Arifureta: From commonplace to World's Strongest
  • Bakuman
  • Code Geass: Lelouch of the rebellion
  • Is it wrong to try to pick up girls in a dungeon?
  • How not to summon a demon lord
  • Komi can't communicate
  • Rent a girlfriend
  • My next life as a villainess: All routes lead to doom!
  • That time I got reincarnated as a slime
  • To Your Eternity
  • Welcome to Demon School! Iruma-kun
  • Yuri!!! on ICE
  • Removed accidental :

  • Fixed typo in Yuri on ice season->seasons

  • Fixed naming to use english title, japanese as synonym

  • Delete stray line

Co-authored-by: Daggersoath 9066690+Daggersoath@users.noreply.github.co Co-authored-by: mizz141 20839616+mizz141@users.noreply.github.com


Thursday 2023-01-12 04:36:15 by willior

consecutive roll mechanics expanded

if you hold a direction when roll_check_queued_actions() is called and roll_queued is true, you will roll in that direction. i have a feeling i might be making it too powerful. will have to adjust roll timing accordingly. i'm also considering raising the stamina cost further for each consecutive roll, eg. roll 1 costs 16 stamina, roll 2 costs 20, roll 3 costs 24, and roll 4 costs 28 (or something like that). that way it's incentivized more as a panic manoeuvre that eats up stamina quickly, with a long recovery (not yet implemented), rather than a technique that can be used all the time. could also go further and lock consecutive rolls behind a Formula Boon, or a charm/accessory/perk/something of that nature. for now, each consecutive roll increases the stamina cost by 4. this is pretty harsh, considering you start the game with 64 stamina. finally, there is a Final_Roll animation which plays if you reach the maximum consecutive rolls, which is 4. the "get up" part of this animation has been lengthened, and player friction is lowered, so you end up in this cool slide before getting up. attacks can still be queued on any of the rolls, however if you queue an attack on the last roll, it won't get the small amount of backwards movement you'd normally get from a roll. speaking of queued attacks... if you perform consecutive rolls, you can keep your charge! your charge is only reset on roll_animation_finished(), which doesn't get called until you either stop chaining rolls or the max roll chain amount has been reached. so your charge will still disappear after a complete roll if you hadn't queued a tech. i hadn't even been thinking about techs yet when i started implementing this mechanic. this is a big improvement in my eyes. it gives the player more options at the cost of stamina, and it makes movement feel a lot better. there's also a degree of skill involved in chaining together consecutive rolls to achieve a queued tech... i would grant a bonus to queued techs from a final consecutive roll, however i don't want to incentivize ALWAYS going for the roll combo - it's an stamina-expensive technique for skillful positioning. still, it is making me want to lower the roll speed a bit, maybe lengthen the default animation. after all, i am playing with the lowest Swiftness stat - it gets pretty crazy at high Swiftness levels with Haste and Frenzy active. for now, i've lowered the default roll speed from 160 to 128. it's a bit sluggish at first, but i suppose that's just how it might be - it's more incentive to level Swiftness. not only is the game becoming fun to play, it's beginning to FEEL quite different depending on your attribute spread, which is fantastic. i want to complete as much of the Player mechanics as possible before moving on to designing more encounters/gameplay situations, and this is a giant leap forward.


Thursday 2023-01-12 05:05:16 by poly-1810

finally fixed the issue

fuck you aureus, making duplicate lifetime


Thursday 2023-01-12 06:18:19 by Zonespace

Mirror 72339 & 71284 (#18645)

  • Renews a bunch of old roundend new reports that got lost. Plus, some roundend report QoL for cult and revs. (#71284)

A few roundend reports got lost from moving to dynamic and other prs. This PRs re-allows them to occur. Namely: "Wizard Killed" (lost in dynamic), "Blob nuked" (lost in dynamic), "Cult escaped" (lost in cult rework), and "Nuke Ops Victory" (station destroyed via nuke) (lost from, what I can see, an oversight / accidental swap of report values).

Additionally, small roundend report QOL for cult: Removes antag datums from spirit realm ghosts after being dusted, so they do not show up on the report. And in reverse, heads of staff who were dusted / destroyed in revolution rounds are now also shown in roundend reports.

Some of these reports are dead, which is is a shame because I think they're cool and fun.

🆑 Melbert qol: Successfully fending off a blob now has a cross station news report again. More pressing reports will take priority over it, though. qol: Successfully killing a wizard (and all of their apprentices) now has a cross station news report again. qol: If more than half of a cultist team manages to escape on the shuttle (rather than summoning Nar'sie), they will send a unique cross station news report. This is still a loss, by the way. Summon Nar'sie! qol: Nuclear Operatives successfully nuking the station now has its unique cross station news report again, and no longer uses the generic "The station was nuked" report. qol: Nuking the station to stop a blob infection now has a unique cross station news report again. Good luck convincing admins to allow this. qol: Cult ghosts from "Spirit Realm" no longer persist on the cult's team after being desummoned, meaning they will not show up on roundend report. qol: Heads of staff will now always show up on revolution roundend report - even if their body was fully destroyed. /🆑

  • Adds support for Rulesets having intrinsic template requirements (#72339)

Title

Ensures that we load templates for a ruleset before we attempt to place or cache characters for that ruleset Also makes wizard and abductor async load their template to improve (apparent) loading times for them

This is the only thing left that I can think of that would cause antags like nukies and abductors to spawn in wrong

This should not be player facing

Co-authored-by: Mothblocks 35135081+Mothblocks@users.noreply.github.com

Co-authored-by: MrMelbert 51863163+MrMelbert@users.noreply.github.com Co-authored-by: Zephyr 12817816+ZephyrTFA@users.noreply.github.com Co-authored-by: Mothblocks 35135081+Mothblocks@users.noreply.github.com


Thursday 2023-01-12 06:52:50 by b9

Ned Batchelder's Digital Logo v1.7, 1989

This was retrieved from an embedding inside a postscript document from a VMS 5.4 disk. It is a hand-tweaked font created by Ned Batchelder of DEC on 24-Apr-1989.

The file itself has extensive commentary:

%%Title: Digital Logo Font, v1.7 %%Notice: The Digital logo is a registered trademark of Digital Equipment Corporation. %%Creator: Ned Batchelder, DEC %%CreationDate: 24-Apr-1989 %%DocumentNeededFonts: Symbol %%DocumentSuppliedFonts: DEC_Logo %%EndComments % % DIGITAL INTERNAL USE ONLY % % INTRODUCTION: % This rendition of the Digital logo was prepared by Ned Batchelder using % Adobe Illustrator and hand manipulation of the resulting PostScript code. % Photographic masters of the logo were obtained from David Comberg in the % Graphic Design Group. Additional consultation was provided by Elliot % Hendrickson, one of the original designers of the logo. % % USE: % This file defines a new PostScript font, called /DEC_Logo. It consists % of three characters. (d) is the entire Digital logo, (t) is a small % trademark symbol, and (T) is a large trademark symbol. The font is designed % so that the argument to scalefont is the height of the logo. There is no % extra white space around the logo at all. The trademarks are designed to be % shown right after the logo, and they align themselves. The only correct % strings to show with this font are (d), (dt), and (dT). There is an entry % (named GapWidth) in the font dictionary which gives the unscaled width of % the gap between the blocks. This distance is given because it is used as a % unit to determine how much space to leave around the logo. % % HISTORY: % The logo was designed in 1957 by Elliot Hendrickson, who was then working % as an independent designer. He was contracted by DEC to do a brochure, and % DEC wanted a logo to accompany it. The logo up to then had been the letters % DEC in blocks the shape of the plug-in cards that DEC had been producing. % Elliot re-worked the logo, incorporating letters which were hand-drawn for % the purpose by Arthur Hover(?). The logo has been maintained since then in % conventional technology, ie, film masters. There was at least one reworking % of the logo at some point. % % The masters I received had a number of interesting features. The boxes were % not all the same width, and there seemed to be no logic to which boxes were % wider. The 'g' was the narrowest, and the 'i' and 'l' were second widest. % Also, the two 'i's were not exactly the same shape. On ten-inch masters, % (one box to an 8x11 sheet), the boxes were not rectangles, but were very % slightly tapered in wierd ways. I assume that the tapering is the result of % too many reproductions, but the difference in widths may have been % deliberate at some time. Elliot reports that when he drew it, all boxes % were the same width. I have made all of the boxes the same width, since % that seems to have been the original intent, since the differences were % almost negligible anyway, and since there was no logic to the differences. % % Please feel free to use this logo, but keep in mind the following: % % 1. This code is for INTERNAL USE ONLY. % 2. I am not entirely happy with the final shapes of the letters, and am % hoping to improve them. Please allow for future updates to this code. % 3. Only use this logo within the guidelines of the Corporate Identity % program. If you use this font precisely as is, you can't get in much % trouble. Don't take the shapes and do strange things with them. % In particular, the Identity states that the logo is a one-color logo: The % letters are actually holes in the blocks, through which the background can % be seen. Do not modify this code so that the letters are always white. % % Edit history: % % 21-Sep-87 nmb Created as a standalone file with demo. % 6-Nov-87 nmb Converted to font form. % 9-Nov-87 nmb Removed // uses for compatibility with LW Classic % 18-Jan-88 nmb Added info about width of logo, since size is usually % specified in terms of width of the logo. (Oops!) % 24-Mar-88 nmb Changed the name to conform to the PostScript name % registration scheme, added FontName, etc. % 20-Jun-88 nmb Removed the long procedure for the logo, and replaced % with a compacted string scheme. % 14-Sep-88 nmb Forced all boxes to the same width; changed the code so % that the boxes and gaps always are the same number % of pixels wide, to improve the appearance at low % resolutions. % 13-Mar-89 nmb Changed the string decoder slightly so that it gracefully % ignores any linefeeds or carriage returns in the % string. % 24-Apr-89 nmb Removed all "bind"s, because bind is a dangerous thing.

[Note from hackerb9: actually, no, this is the version that does use bind. I found an older version that does not, but haven't seen a newer yone, yet.]


Thursday 2023-01-12 08:31:42 by leycec

__beartype_hint__() x 4.

This commit is the next in a commit chain defining the PEP 544-compliant beartype.plug.BeartypeHintable protocol, en-route to resolving feature request #192 technically submitted by myself but spiritually submitted by super-nice NIST scientist @tbsexton (Thurston Sexton) in his unquenchable search for a utopian DSL for typing Python that may never exist – but should. Specifically, this commit continues iterating on the implementation, usage, and testing of this protocol. Sadly, we suddenly realized in a fit of mad panic that this protocol should not actually be a protocol. Why? Because doing so coerces all user-defined classes subclassing this protocol into typing generics -- which is absolutely not intended. Consequently, the next commit in this commit chain will:

  • Relax BeartypeHintable into a standard abstract base class (ABC).
  • Create a new private _BeartypeHintableProtocol for internal usage, mostly in detecting classes implicitly satisfying this ABC.

(Thunderous terror or tons of nuns on tundra?)


Thursday 2023-01-12 12:47:51 by Mike Griese

Manually copy trailing attributes on a resize (#12637)

THE WHITE WHALE

This is a fairly naive fix for this bug. It's not terribly performant, but neither is resize in the first place.

When the buffer gets resized, typically we only copy the text up to the MeasureRight point, the last printable char in the row. Then we'd just use the last char's attributes to fill the remainder of the row.

Instead, this PR changes how reflow behaves when it gets to the end of the row. After we finish copying text, then manually walk through the attributes at the end of the row, and copy them over. This ensures that cells that just have a colored space in them get copied into the new buffer as well, and we don't just blat the last character's attributes into the rest of the row. We'll do a similar thing once we get to the last printable char in the buffer, copying the remaining attributes.

This could DEFINITELY be more performant. I think this current implementation walks the attrs on every cell, then appends the new attrs to the new ATTR_ROW. That could be optimized by just using the actual iterator. The copy after the last printable char bit is also especially bad in this regard. That could likely be a blind copy - I just wanted to get this into the world.

Finally, we now copy the final attributes to the correct buffer: the new one. We used to copy them to the old buffer, which we were about to destroy.

Validation

I'll add more gifs in the morning, not enough time to finish spinning a release Terminal build with this tonight.

Closes #32 🎉🎉🎉🎉🎉🎉🎉🎉🎉 Closes #12567

(cherry picked from commit 855e1360c0ff810decf862f1d90e15b5f49e7bbd)


Thursday 2023-01-12 13:48:22 by NotAKidoS

attempt to fix compatibility with more avatars

(Fuck you Default Robot Kyle)(Fuck you Default Robot Kyle)(Fuck you Default Robot Kyle)(Fuck you Default Robot Kyle)(Fuck you Default Robot Kyle)(Fuck you Default Robot Kyle)(Fuck you Default Robot Kyle)


Thursday 2023-01-12 14:14:46 by Chris Thorpe

Merge pull request #17 from chris-thorpe3db/dev

Merge commit 32fdf46 (god fucking damnit)


Thursday 2023-01-12 16:32:48 by Michal Vlasák

tools: labs: qemu: Add run-qemu.sh as alternative

TL;DR: In one window run make -j$(ncproc) console and cd to some lab's subdirectory (skels/...). In second window cd to matching skels/... subdirectory, edit source files and compile with something like kmake (alias kmake='make -C "$HOME/src/linux/" M="$(pwd)"') as needed. The skels directory is shared between the host and the guest, thus in the first window, so you can just insmod and rmmod the compiled modules. You can kill the VM by CTRL-a x (if you made some writes from the VM it might be a good idea to run sync first). Samba and QEMU are required.

Full description:

To be honest I don't like the current QEMU setup. I am sure there are things it does that I don't understand yet, because I have not yet finished all the labs, but in any case I think that the setup can be improved.

Some things in particular I don't like about the current setup:

  • "Huge" opaque .ext4 images are used, even though the contents of the root file system are not that large.
  • While running QEMU newly built modules can't be copied to the image.
  • Mounting and unmounting the .ext4 image for copying the modules requires sudo.
  • The networking setup seems too complex, requires sudo and was broken (at least for me - IIRC I didn't get IP through DHCP), thus I also didn't get ssh to work. I also seem to be not the only one having issues with this: linux-kernel-labs/linux#240 (comment)
  • dnsmasq and nttctp mostly don't start correctly (they are not killed correctly by the previous run) - this isn't a problem on my end, as demonstrated by the output at https://linux-kernel-labs.github.io/refs/heads/master/info/vm.html, which shows the same issues.
  • Running minicom is required to access the serial port, thus at least two terminals are required for working with the VM (not a huge problem for me personally, since I use tmux, but I know some people complain about this). The setup also seems unnecessarily complex.
  • I remember a lot of the .mon .pts files being left uncleaned in some cases.
  • I recall warnigns about some of the entries added to /etc/inittab being ignored.
  • Even though root login requires no password I have to enter the root username.

In this commit I introdoce an alternative way of running QEMU through a new run-qemu.sh script. The setup is laregely independent and its user interface consists of console and gui targets. I tried to make the script parameterizable through environment variables (inherited from Make variables), though it may be argued that the default values should be encoded in Makefile rather than in the script like they are now. I have no strong opinions about that, it's' just that the current state allows running the script in standalone fashion.

What the setup brings:

  • A rootfs is extracted from the official Yocto Project tarball and kept in a directory that is shared through Samba as network share. The skels directory is shared as well. Thus the modules can be freely tweaked / compiled / ran from either the host or guest.
  • The QEMU stdio serial console setup is used (ttyS0 on the kernel side). This means that running QEMU results in the serial console being mapped directly to standard input and output of the terminal - minicom is not needed. This is the console mode (make console).
  • The setup allows also allows the virtual machine to be run in graphical mode (make gui).
  • Root is logged in automatically in console mode (though similar thing could be done for the gui mode).
  • Although Samba (smbd) is required, sudo or root access is not.
  • Networking through QEMU's default SLIRP backend. DHCP is handled by the kernel, which overcomes some problems I had with the System V init system in the Yocto images.
  • The compilation can largely be done with something like this kmake alias: alias kmake='make -C "$HOME/src/linux/" M="$(pwd)"' (customize as needed). Though this is not enough for some labs (I no longer remember the details, but I think it was some of the earlier labs which had dependencies between modules, I think I used the classic make build for that.

Known issues:

  • SSH support is currently missing. This both requires more featureful Yocto images and is IMO unnecessary, since it wouldn't bring much benefit over the console mode. Though it can be easily achieved by using QEMU option like -nic user,hostfwd=tcp::2222-:22, which would allow SSH'ing into the guest by something like ssh -p 2222 root@localhost.
  • I used a slightly less advanced setup while doing the labs, so the lab workflow with this particular setup is largely untested. There may be problems with file permissions due to the samba share.
  • The guest seems to fail to shutdown correctly in a timely manner. I just took the habbit of killing qemu with CTRL-a followed by x, potentially running sync first to ensure my work is saved (though rarely did I actually modify anything on the guest side).

The former setup I used contains some details of the SSH setup if anyone is interested in that. It was the basis for this PR, so some ideas can be seen there (Samba share for skels), but I didn't take particular care with the kernel config and the automounting didn't really work (the init would try to mount the filesystem before networking was up).

What I evaluated and didn't use in the end:

  • At first I tried to extend my former setup by just automounting the Samba share. I didn't manage to do this - the (non)workings of init scripts seem to be beyond me. If anyone is interested here are a few pointers: [1], /etc/inittab, /etc/init.d/mountall.sh, /etc/init.d/mountnfs.sh.
  • I tried using 9p [2], [3] [4] which is built into QEMU and can be compiled into the kernel. With mapped-xattr security model it would be too cumbersome to create the rootfs, and passthrough would require root privileges. It is also very slow. There are also some problems with trying to use it as rootfs, maybe specific to linux-kernel-labs kernel version or config. Ask me if interested. [5] [6] [7]
  • QEMU has an option to setup the Samba share on its own, though I found a custom config (based on the QEMU one) to be easier - allows customization like multiple shares, unix extensions, different port, etc.

Thursday 2023-01-12 16:39:53 by SkyratBot

[MIRROR] Avoid creating string list of turf platings, rename some of the APIs, and improve focused test support - 160ms+ (more on prod) of init savings [MDB IGNORE] (#18357)

  • Avoid creating string list of turf platings, rename some of the APIs, and improve focused test support - 160ms+ (more on prod) of init savings (#72056)

Looking at some stuff that uses Join right now as targets, this one's pretty straight forward.

/turf/open/floor/Initialize, called 20,000 times without ruins, creates a string list of the broken and burnt states. This carries the fixed cost of Join, which is very expensive, as well as some (not crazy, but not negligible) proc overhead.

These vars were used for effectively nothing, and have been replaced with just using the list when necessary, which only adds an extra millisecond of cost to update_overlays.

This was also used to automatically set broken and burnt at runtime. However, this looks like it has gone completely unused. Adds a unit test which adds it as a static field to the only type that cared about it, which was abductor tiles, which is wrong anyway, but Whatever. I want to support people making a subtype of floor tiles that are pre-broken without it messing up stuff silently, so the test is there.

While I'm at it, renames setup_broken_states and setup_burnt_states to remove setup_, since they don't really do that anymore (and never did).

Also also, adds support for PERFORM_ALL_TESTS to work with multiple focuses.

For reviewing, basically all of the changes are in floor.dm, aside from test stuff, which is unit_test.dm.

  • Avoid creating string list of turf platings, rename some of the APIs, and improve focused test support - 160ms+ (more on prod) of init savings

  • a

  • FUCK

  • nope

Co-authored-by: Mothblocks 35135081+Mothblocks@users.noreply.github.com Co-authored-by: John Doe gamingskeleton3@gmail.com Co-authored-by: Tastyfish crazychris32@gmail.com


Thursday 2023-01-12 16:43:55 by SkyratBot

[MIRROR] Completely Culls req_access_txt/req_one_access_txt [MDB IGNORE] (#18458)

  • Completely Culls req_access_txt/req_one_access_txt (#72281)

Hey there,

Now that every instance of req_access and req_one_access is a list of strings, there is absolutely no reason for req_access_txt/req_access_one_txt to exist. In fact, any instance where they were still used in the codebase was very convoluted and was very broken! Don't worry, I fixed it all out, and life is good.

I also dmdoc the surviving access variables, because those were missing. I went on the side of caution and made a more verbose documentation with an example just to have people really grasp this (it took me a while to actually get it)

I believe that we changed everything over to the req_access/req_one_access system earlier this year in VV, but the problem is that new mappers don't understand the difference between the two systems. In fact, the "txt" system is completely redundant since all it does is transition stuff to the "base" system. So, let's just completely cull the one that's all but deprecated and ensure this confusion no longer arises. The whole purpose of "txt" seemed to be to convert the access, but it's all pointless now that we can just read the list directly.

I'm also 99% certain that the "access check" on vending machines broke (and didn't seem to have correct logic in the first place? I legitimately couldn't find a case where it could fail in testing, so I changed that up), and that's fixed up now. Let me know if I was clueless there. I know it's short-circuiting now as opposed to "all must be true", but it just didn't work.

  • Completely Culls req_access_txt/req_one_access_txt

  • oh the misery

  • makes them use the thing that actually works

  • test to see if engineering access is breaking it

  • Revert "test to see if engineering access is breaking it"

This reverts commit 3cc2c554ff18f435a51601782e64c76193298db7.

  • Fix access checks when req_access is null (#72458)

About The Pull Request

Fixes #72450 - This seems to be an oversight in some of the access refactors we've been through recently. When there was an assumption in check_access_list() that req_access would always be a list, and that if it was not something terrible had gone wrong and the door should default to public access.

With the cleanup of the _txt access vars and the introduction of mapping access helpers, this assumption is no longer true. req_access will be null when multiple helpers are painted onto the same door, so we need to handle that properly. Thanks to @MrMelbert for spitting out the attached fix in mapping general and letting me PR it after testing.

This really needs a suite of unit tests around it. San has helpfully volunteered to work on that for three hours before getting frustrated.

Why It's Good For The Game

No more public access to engineering lobby, lathe, etc.

Changelog

🆑 Vire, MrMelbert fix: The engineering lobby and lathe are no longer public access fix: Doors will no longer be treated as public access when they have multiple accesses set on them /🆑

Co-authored-by: san7890 the@san7890.com Co-authored-by: Paxilmaniac paxilmaniac@gmail.com Co-authored-by: Vire 66576896+Maurukas@users.noreply.github.com Co-authored-by: Tastyfish crazychris32@gmail.com


Thursday 2023-01-12 17:06:26 by ReticenceVat

Create The Backpage of Desires&Thoughts@All That's In FrontIsALie|USeeBackOfMyThoughtSoWhyWon'tUBeNowMy

don't..send me no angel/as i want what's all/that gives me my boo whatever is me may all fall/don't ring in attention..as i want to be/with whatever will be liked by me.. oh second..wind/let us swing/don't now you by being else..pat me oh God.. don't send me no angel.. as i want to shove.. whatever was just me but didn't end my desire oh my lord.. i've learnt I will be mindful..hihi..Come..SecondWind


Thursday 2023-01-12 17:06:38 by Romain Derie

[FIX] website: redirect to case insensitive URL if not exact match

Before this commit, if a link to a page was not correct because of a case mismatch, it would simply land on a 404 page. While it's correct, as URL are case sensitive, it leads to a few bad UX flow at the admin/editor level:

  • Create a link in your page (on a text or a button eg), type an URL which does not exists (to create it after) like /Page
  • Click on the link/button you just made, you are redirected to /Page which display a 404 with the "Create page" option (correct)
  • When you click on that button, it will actually create a page with /page URL, leading to a mismatch between the URL you created and the page URL. Your link/button will still lead to a 404 URL as it points to /Page.

Since it's just a fallback when an exact URL match is not found, it should not break anything and should not have bad impact at any level (seo/speed etc). Indeed:

  • It's done through a 302 redirect
  • _serve_page() is already a fallback case, so it will only make the website.redirect and 404 cases a bit slower due to the extra search query.

The only possible scenario seems to be if the user (mind the case):

  • Created a /Page page
  • Created a redirect from /page to /another-page

In this case, /page won't land on /another-page but on /Page. This flow seems unlikely and is not actually wrong either way. At least, it certainly is less important than ensuring a case insensitive fallback.

Finally, note that another solution would have been to either:

  • Force page URL to lower case. -> This is not stable friendly, people might be relying on this to create pages with different casing: /Batman-VII-The-Dark-Knight-Whatevers, while not recommended, doesn't sounds idiot. On top of not being stable friendly, we probably want to keep offering this possibility
  • Redirect all URLs to lowercase endpoints. -> This is obviously not stable and not Odoo's jobs. It should be something decided by the sysadmin and done at nginx (etc) level.

task-3110294 opw-3104030


Thursday 2023-01-12 17:39:28 by Michał Bundyra

Message against the war, in Russian and English

🇷🇺 Русским гражданам

Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.

У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.

Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"

🇺🇸 To Citizens of Russia

We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.

One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. Were not taking this from any media. These are our actual experiences.

You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"

Signed-off-by: Michał Bundyra contact@webimpress.com


Thursday 2023-01-12 17:51:49 by DinkyRajpoot56

Update Sentithon.py

Over 4.59 billion people used social media worldwide in 2022; by 2027, this number is expected to reach nearly six billion (see Figure 1).1 Social media platforms are important sources of data, because the data generated by users on social media channels is readily available to companies. Uses of social media data includes research and marketing, among others.

In order to analyze social media data, data extraction is necessary. Web scraping tools help organizations extract data from multiple social media platforms.

In this research, we will dive into each aspect of social media scraping, including what it is, why it matters, its benefits, legality, tools for social media scraping and types of data that can be collected from top social networks.

Figure 1: Global social media user population from 2017 to 2027

Number of social media users worldwide from 2017 to 2027. Source: Statista What is social media scraping? Social media scraping is a process of automatically extracting data from social media platforms including:

Twitter Facebook Instagram What is the best way to scrape social media platforms?

  1. Web scraping tools You can use automated data collectors to extract data from social media platforms. Web scraping tools, for example, enable businesses to automatically collect social media data. The following are a few examples of how web scrapers are used in various industries:

Restaurants utilize web scraping tools to track and extract social media data such as menu, delivery items to gain insight into their products and services. Web scrapers enable businesses in the travel industry to extract hotel and tourism data from social media platforms by using specific keywords and hashtags. You can either:

Build your own scrapers using web scraping libraries (in-house web scrapers). Utilize an open source web scraper. Use one of the following off-the-shelf web scrapers (see Figure 2). Low/no code web scrapers Cloud web scrapers Browser extensions web scrapers Figure 2: Off-the-shelf web scraping solutions

Companies can either build their own scrapers using web scraping libraries or use off-the-shelf scrapers such as low/no code web scrapers to extract data. 2. Web scraping APIs Web scraping APIs are an alternative method for extracting data from social media platforms. It enables clients to access and extract data from web sources by using an API call. You can utilize a commercial web scraping API solution or a third-party scraper API such as Twitter API, Instagram API, etc.

Code-based web scraping solutions such as scraping APIs allow users to customize scrapers based on their specific business requirements. You can outsource your web scraping infrastructure if you lack the programming skills to build the web scraping code environment and if cost is not your main concern.

  1. Web scraping with RPA Robotic Process Automation (RPA) web scraping automates data collection tasks and reduces the workload on the web scraper. Businesses can use RPA bots to:

Eliminate manual data entry and minimize the risk of human error. Scrape a large quantity of data and accelerate data collection processes. Extract image and video data. Some web scrapers only extract the image URL and do not extract visual data such as images, videos, GIFs, etc. Top 3 business outcomes of scraped social media data

  1. Have a customer-centric strategy Businesses need dynamic data in order to be customer-centric. Data scraped from social media channels provides dynamic information about individuals and is updated on a regular basis as new information becomes available.

Customers use social media platforms to express their preferences, complaints, and expectations regarding products. A data scraper can collect review data from websites and social networks. It provides companies with an organic approach to their services and products.

Real life example: Spotify has built a Twitter account, SpotifyCares, to monitor customers’ brand-related tweets and respond to them. (see Figure 3). Twitter data enables Spotify to:

Better understand the concerns and expectations of its customers. Uncover questions about the company’s services on Twitter. Develop relationships with potential customers. Improve their customer service and social listening strategy. Figure 3: Example of customer interaction on Twitter

social media scraping for customer services 2. Keep up with the latest trends Market changes may have an impact on your customers’ expectations for your products and services. You need to extract current market data to understand customer preferences and expectations. Social media accounts, blogs, wikis, and other websites are all important places to look for information about what your competitors are up to and how they’re performing.

For example, customers’ feedback on their products provides insight into the types of techniques that are successful for them. Social media scraping bots automatically extract data and provide you with structured data that is ready to be analyzed. It enables businesses to update their strategies, and gain a better understanding of market trends.

Sponsored

Bright Data’s Data Collector extracts data from any public website on a large scale. You can choose the time lags, such as real-time or scheduled. It cleans, synthesizes, and structures the data from unstructured websites. The data is delivered as JSON, CSV, HTML, or Microsoft Excel.

Real-life example: Brandwatch used Twitter data for social listening and keyword monitoring.2 The company used social media data to help Co-op, one of the largest food retailers in the UK, with its Twitter marketing campaigns.

The Co-op had difficulty gaining:

Real-time social insights Tracking their marketing campaigns Ensuring their success. Brandwatch used Twitter data to provide Co-op with real-time insight into brand mentions and trending conversations about its competitors. With Twitter data, the company’s campaign reached 23.5 million people and generated 75 million impressions.

  1. Conduct sentiment analysis Scraped social media data enables brands to identify the positive/negative words describing their products and services (see Figure 4). For instance, you can collect a specific number of tweets that contain your brand’s specific keyword or hashtag using a data collection tool or API solution.

Twitter’s own API allows users to access and collect Twitter data, such as tweets, media, number of users, etc. Then, you can analyze the sentiment of the collected tweet to measure the brand’s negative, neutral, or positive public perception. However, you must be aware of fake product reviews and content generated by bots to ensure the accuracy of your collected data.

Figure 4: Words used to describe products & services based on an analysis of customer reviews

Social media scraping allows brands to analyze customer reviews for sentiment. Source: AIMultiple Real-life example:

Mathison is a DEI (diversity, equity, and inclusion) platform that helps businesses with their hiring processes. To create a unified talent pool, the company collects candidate data from various web sources such as recruitment websites and social media platforms such as LinkedIn.

Mathison used Bright Data’s data collector to gather massive amounts of candidate public data from web sources like LinkedIn. It streamlined data collection and reduced the time required to collect candidate profile information manually (see Figure 5).

Figure 5: Case study of web scraping for a centralized talent network for recruiters

web scraping case study in recruitment Legality & types of data that can be collected from social networks Scraping publicly available data is legal; there are no laws or regulations prohibiting it. However, this doesn’t imply that you can scrape everything. Private information and copyrighted content are both protected by law.

If you wish to scrape private data you should read the General Data Protection Regulation (GDPR).

Facebook With 2.89 billion monthly active users, Facebook is the largest social networks in the world (see Figure 6). 3 Scraping Facebook data is legal as of 2023. However, scraping private content without permission and selling it to a third party for a profit without the user’s consent is not permitted.

You can scrape information that is publicly available, such as:

Username, profile URL, profile photo URL, following and followers information, likes and interest themes, and so on are all included in profiles. Posts include information such as the date, location, number of likes, views, and comments, as well as text and media URLs. Figure 6: Most popular social media platforms worldwide

Facebook, with 2.89 billion monthly active users, is the world's largest social network. Source: Semrush Twitter Twitter is just another trove of data that can be utilized to track brand sentiment and gauge client satisfaction. Twitter’s APIs provide companies with free access to Twitter data. To use the Twitter API, you must first register.

The most significant benefit of the API is that, because it is supported by Twitter, there is no fear of being blocked as long as you pull data in accordance with their API requirements. However, the API has some limits; it can only scrape 18,000 tweets per 15-minute window.

Scraping publicly accessible Twitter data is typically legal, but you need to check whether the content is crawlable or not with the robots.txt file. It provides or denies access to URLs and specific content on a website. Data that can be collected from Twitter include:

Keywords / hashtags: By searching your brand hashtags, location-specific hashtags, and audience-specific hashtags, you can extract useful data for your business. Tweets: You can get a list of all the tweets of specified profiles. Profiles: you can collect all the information about a Twitter user’s public account such as their bio, numbers of followers & following. To learn more about twitter web scraping, read our comprehensive article on the topic.

Data Collector tool enables organizations to crawl and scrape publicly available data such as Twitter profiles (see figure 7), URLs, tweets, and retweets from Twitter in real-time.

Figure 7: It is the output of “https://twitter.com/billieeilish” URL. Data Collector uses Billie Eilish’s Twitter profile to extract data such as her followers, following, and bio & post information.

The image shows the the output of
Source: Bright Data YouTube It is legal to scrape data from YouTube so long as you do not interfere with the website’s operations and do not collect personally identifiable information (PII). According to the research, 85% of SMBs have used YouTube data to reach new audiences and grow their customer base.4 The data listed below can be extracted from YouTube:

Video title and description Comments on videos Video ID Number of views and likes Check out our guide to scraping YouTube data to learn more about its legality, use cases, and best practices.

Figure 8: The process of data extraction from YouTube

The image explains each step for scraping YouTube data. Instagram Instagram gives businesses and professionals access to their posts and comments on them. You can automatically extract public data from Instagram profiles and hashtags without any blocking. A scraper bot enables organizations to scrape and extract data including:

Profiles: scraper bot extracts information such as posts, followers & following, and external URLs. Comments: Post date, post date, post URL, comments, likes. Hashtags: Post URL, media URL, post author ID. Further reading on web scraping: 3 Ways to Gain Competitive Edge with Amazon Data (With Tips) The Ultimate Guide to Review Scraping : How-to & Best Practices Top 5 Web Scraping Case Studies & Success Stories Download our whitepaper on web scraping if you want to learn more about it:

Get Web Scraping Whitepaper

Check out our data-driven list of web scrapers for help choosing the right tool, and get in touch with us:

Find the Right Vendors

Number of social media users worldwide from 2017 to 2027 (June 2022). Statista. Retrieved 10 January, 2023. “Four ways Brandwatch and Co-op use Twitter across different time frames“. Twitter. Retrieved 8 January, 2023. “Most popular social networks worldwide-2022“. Statista. Retrieved 8 January, 2023. The State of The Creator Economy (2021). Oxford Economics. Retrieved 8 January, 2023.

Share on LinkedInShare on Twitter Gulbahar Karatas Gülbahar is an industry analyst of AIMultiple. She received her bachelor’s degree in Business Administration from Dokuz Eylül University.

RELATED RESEARCH Web scraping enables businesses automatically extract food and restaurant data from food ordering websites. Web Scraping TOP 5 WEB SCRAPING USE CASES IN THE FOOD INDUSTRY IN 2023

Web Scraping , Proxy DATACENTER VS. RESIDENTIAL PROXIES: WHICH TO CHOOSE?

Web Scraping , API WEB SCRAPING APIS: HOW-TO, CAPABILITIES & TOP 10 TOOLS IN 2023 Leave a Reply YOUR EMAIL ADDRESS WILL NOT BE PUBLISHED. REQUIRED FIELDS ARE MARKED *

Comment * Name Surname

E-mail Address

POST COMMENT 0 Comments Subscrib


Thursday 2023-01-12 18:05:52 by Steven L

Standardizing cancellation behavior: a canceled workflow never starts a new run (#4898)

Summary for busy people

Workflow cancellation was kinda weird and confusing, and left some awful, unrecoverable, and un-preventable edge cases (particularly with child workflows). It also left users with no way to reliably stop work, aside from termination. Termination is inherently "unclean" and risky, so it should not be required to achieve something outside exceptional circumstances where recovery is not possible.

This commit changes that: cancellation is now "sticky", and a canceled workflow does not ever trigger a new run after it completes, regardless of how it completes, so it can be used as a reliable "stop processing after cleanup" tool. The final state of a canceled workflow's run is now always a successful completion with a value, canceled, or timed out. (termination remains always "terminated")
A canceled workflow can still start and abandon child workflows, so all current behavior with retries / continue as new / etc can be replicated with child workflows if desired.

A fair bit of (not very complex) additional work here and in nearly all other repos is required to truly complete this, but it is functional and non-optional with this commit alone.
In particular, adding a dynamic config to (temporarily!) restore old behavior should be fairly easy if it proves to be needed.

More details and motivation

Part 1 of [many, tbd, in multiple repos] involved in changing workflow cancellation to reliably end workflows. Tests will be coming soon, for now I'm using a fairly simple set of workflows and checking the resulting histories exhaustively by hand.

The primary motivation for these changes is to address some impossible-to-recover-from scenarios when canceling child workflows. After further exploration and discussion we've realized that, without these changes, there is no reliable way to stop a sequence of workflows without relying on termination, which we consistently treat as a fallback / impure-but-necessary ultimate hammer.

Workflows should not need to rely on termination to achieve a desired behavior. With these changes, cancellation becomes capable of guaranteeing that workflows end within some finite time, which is a unique ability and makes it much more consistent and reliable.
Turning this into a "complete" change will require quite a few tests, documentation changes, client-side changes (to allow recording more info, and likely changing test suites), and some smallish database and maybe RPC changes (to hold/return more data in cancellation errors).

We are also not currently planning on making this configurable. It's seen as a correction of an under-specified and somewhat flawed chunk of behavior, more than "a change".
Existing workflows will not experience replay errors, but it is still a substantial semantic change, though from what we have seen cancellation is relatively rarely used (partly due to its complex behavior). If issues are encountered / if users end up needing it, it should be fairly easy to add a per-domain/tasklist/workflow type configuration value, but it will be opt-out, not opt-in.

What was happening

Previously, workflow behavior on cancellation was pretty frequently surprising to our users, arguably inconsistent, and not very well documented:

PREVIOUS simple retry cron retry+cron
success success success success
continue cron
cron
success
continue cron
cron
retry
cancel canceled canceled canceled canceled
retryable (n/a, fatal) continue retry
retry
recorded error
(n/a, fatal) continue retry
cron
retry
recorded error
fatal failed
recorded error
failed
recorded error
continue cron
cron
recorded error
continue cron
cron
retry
recorded error
continue continue immediately continue immediately
retry
continue immediately continue immediately
retry
timeout timeout continue retry
retry
recorded error
continue cron
cron
recorded error
continue retry
cron
retry
recorded error

A legend is:

  • success / etc shows the final state of the canceled run (success = completed with a value that can be retrieved)
  • "continue X" covers what source is used to compute the next run's starting delay (cron, retry, or no delay)
  • "cron" / "retry" shows whether or not cron/retry configuration is carried over to the new run
    • note that cron is lost by default with continue-as-new
  • and "recorded error" is whether or not the returned error is saved in its entirety (type + reason + details)

This largely summarizes as "cancellation works when you end with the canceled-context error", say from ctx.Err(), otherwise it behaves like normal (or nearly) and many scenarios will start a new run. That's somewhat reasonable, but it's fairly "fragile" (it depends on what you return, and there are many ways for code to return some other error), and most importantly it means there is no reliable way to stop a workflow except to terminate it.

That has severe consequences in at least two scenarios:

  1. When termination is unsafe
  2. When a parent workflow cancels a child by canceling its context

For 1, for manual cancellations it's potentially reasonable to just terminate a run that begins after a successful cancel... but in principle if you're using cancellation it implies that termination is not desired, and potentially not safe to do. Canceling may result in a brand new run that immediately starts new behavior, leaving you with no safe window to terminate and not leave bad state lingering.
So users wanting a safe way to stop a sequence of workflows have no reliable way to do so.

For 2, it puts parent+child workflows in an extremely awkward, and essentially unrecoverable scenario. Cancellation is a one time event, and as far as the parent is concerned, if the child/its context is canceled, the child is canceled...
...but if the child then starts a new run for any reason (retry, cron, reset, etc), that new run is no longer canceled. The parent has no way to know this has happened, and has no way to re-cancel the new child, so it can easily lead to the collection of workflows getting into an impossible state that it never recovers from.

Both cases are able to lead to unreliable behavior which can only use termination to stop, and for which no "safe" option exists.

After reviewing some customer issues and desires and thinking about things, we've settled on "cancel should guarantee that things stop". Not necessarily in a timely manner, but that's fine. And if a workflow wants to run behavior longer or larger than its current run can achieve, it has a workaround: start a new (likely child) workflow to do the cleanup.

What happens now

So that's what this PR does, in a minimal / to-be-polished way so we can start running it for our stuck users while we flesh out tests and change other behaviors.

Currently that means our cancellation behavior is now:

CURRENT simple retry cron retry+cron
success success success success success
cancel canceled canceled canceled canceled
retryable (n/a, fatal) canceled
recorded error (details only)
(n/a, fatal) canceled
recorded error (details only)
fatal canceled
recorded error (details only)
canceled
recorded error (details only)
canceled
recorded error (details only)
canceled
recorded error (details only)
continue canceled
(no details)
canceled
(no details)
canceled
(no details)
canceled
(no details)
timeout timeout timeout timeout timeout

And the new "details" entries cover whether or not an error's "details" (the custom encoded data, not reason or type) are saved. Unfortunately the current cancellation event (and clients' API) does not allow recording all data, or any in some cases, so the original reason/message and error type are lost and are replaced with a canceled error.

Now, cancellation always ends workflows with the current run. Returning a value will return that value, including in cron scenarios, timeouts are still timeouts (and they imply a possibly un-clean termination), and all errors or attempts to continue-as-new will instead result in a canceled state.

Future changes to make to finish this effort

With further changes to the clients and RPC/storage models, canceled errors will store more details about what was returned. E.g. continue-as-new does not record what was attempted to be started, and other error types lose their "reason" (i.e. the message) and type but not details. Pretty clearly this is sub-par, and we should be capable of reporting the actual return in full so it can be retrieved if needed. This is also why returning a value now always ends in a completed state, so successful completions do not lose those values.

Prior to merging into master / a release, we may end up making this configurable (likely with a default of opt-out), to address both the sub-par information recording and the semantically-breaking behavior change. Docs changes are also due, as well as some integration tests, client library changes (e.g. to make sure the test suite reflects the new behavior), etc.

Another gap to plug is that resetting a workflow does not "forward" the canceled state to the new run. We should probably be treating cancellation like we do signals: cancel the new run if the current run is canceled. This will ensure that you can reset a child and retain the parent's cancellation, so it'll very likely become the default behavior, but we'll allow overriding it. Resets are manual actions, they can break the rules if desired. And they can just manually cancel later if they decide they do want it.

And last and perhaps least: it's quite strange that continue-as-new does not retain cron config. At least from the Go client. I suspect it's just not adding to / pulling from the context correctly.


Thursday 2023-01-12 23:08:06 by LeoniSayat

working on roller, i hate my life and this programming skills


< 2023-01-12 >