Compile error with --mtriple=s390x-ibm-zos

After commit https://github.com/onnx/onnx-mlir/commit/58572e00c3805a5c07918909264ea52c612a7448 compiling with --mtriple=s390x-ibm-zos results in a compile failure.
The commit sets the default of src/Accelerators/NNPA/Compiler/NNPACompilerUtils.cpp  to true.
Here's the compile command options and error output:
-EmitObj  -O3 --onnx-op-stats=TXT --mtriple=s390x-ibm-zos --mcpu=z16 --maccel=NNPA /models/mnist-12.onnx
[1/5] Tue Jul 23 17:54:56 2024 Importing ONNX Model to MLIR Module
[2/5] Tue Jul 23 17:54:56 2024 Compiling and Optimizing MLIR Module
Operations encountered:
-----------------------
  func.func        , 1
  func.return       , 1
  onnx.Add        , 1
  onnx.Constant      , 2
  onnx.NoValue      , 1
  onnx.Reshape      , 1
 zhigh.Conv2D       , 2
 zhigh.MatMul       , 1
 zhigh.MaxPool2D     , 2
 zhigh.Stick       , 2
 zhigh.StickifiedConstant , 5
 zhigh.Unstick      , 2
[3/5] Tue Jul 23 17:54:56 2024 Translating MLIR Module to LLVM and Generating LLVM Optimized Bitcode
[4/5] Tue Jul 23 17:54:56 2024 Generating Object from LLVM Bitcode
<inline asm>:1:1: error: HLASM Label has to start with an alphabetic character or the underscore character
.insn vrr,0xe60000000075,0,0,1,0,2,0
^
<inline asm>:1:1: error: HLASM Label has to start with an alphabetic character or the underscore character
.insn vrr,0xe60000000075,1,1,2,0,2,0
^

Please set the default for  enable-compiler-stick-unstick  to false for zOS and then  re-enable to a default of true for once this issue is corrected.

Once fixed, we should revert #2888

@mikeessen any progress on this?

@mikeessen any progress on this?

Yes, I have made progress, but not yet ready to commit.

@mikeessen I think your PR went in to fix this. Please close if appropriate

Thanks for reminder @AlexandreEichenberger
Fixed with https://github.com/onnx/onnx-mlir/pull/2974


h2rbox v2 test results?

Hello,
Thanks for the code, I am able to train a H2RBoxv2 model  on DOTAv1 and I obtain the following results by the end of the training::

I assume these correspond to the validation scores at the end of the training, since the test annotations are not provided by the authors of DOTA. Hence, do the tables reported in the paper correspond to the results on the test set? Do you extract them by uploading the predictions on the evaluation server?
Thanks

yes, you are right.

I fix some bug in h2rbox-v2 config:
https://github.com/yangxue0827/RSG-MMRotate/blob/db7d2a4f97737399a0b9f72a0af85b351704dced/configs/h2rbox_v2p/h2rbox_v2p_r50_fpn_1x_dota_le90.py#L82-L95
The previous version still used rbox supervised learning.

Hi, I applied the changes on the h2rbox-v2 config file and I got similar results as before. In fact, I am quite confused by the nested_projection method in the H2RBoxV2PHead class, which is used to compute the target and predicted horizontal boxes from their respective oriented ones as weak supervision.
def nested_projection(self, pred, target):
        target_xy1 = target[..., 0:2] - target[..., 2:4] / 2
        target_xy2 = target[..., 0:2] + target[..., 2:4] / 2
        target_projected = torch.cat((target_xy1, target_xy2), -1)
        pred_xy = pred[..., 0:2]
        pred_wh = pred[..., 2:4]
        da = pred[..., 4] - target[..., 4]
        cosa = torch.cos(da).abs()
        sina = torch.sin(da).abs()
        pred_wh = torch.matmul(
            torch.stack((cosa, sina, sina, cosa), -1).view(*cosa.shape, 2, 2),
            pred_wh[..., None])[..., 0]
        pred_xy1 = pred_xy - pred_wh / 2
        pred_xy2 = pred_xy + pred_wh / 2
        pred_projected = torch.cat((pred_xy1, pred_xy2), -1)
        return pred_projected, target_projected

        return pred_projected, target_projected

Here, the target angle (i.e. the angle ground truth information) is being used to extract the pred_projected tensor, as the angle difference da = pred[..., 4] - target[..., 4] seems to be used to refine the prediction's height and width pred_wh. Shouldn't we refrain from using the ground truth angle since we are supposed to not have that information?

@yuyi1005

The ground truth angle is usually 0 or pi/2 for horizontal boxes, but when the random rotation augmentation is applied, these target boxes could have an angle. "da" is the angle difference between the internal rotated box and the external circumscribed box (either rotated or horizontal).
The results you provided (82.8% on trainval set) seems correct. You can also run tool/test.py and upload the zip file to the DOTA server to obtain the results on test set.

I see, so if I understood correctly: after applying random rotation the originally horizontal bounding box becomes oriented, and the code extracts the prediction's circumscribed bounding box oriented by the same angle.
For the results, I would love to test them on the server but I can't get the confirmation email after sign up.
It is more clear now, thanks!

Gmail email addresses may not be able to be registered as they require the email suffix of the organization, e.g. sjtu.edu.cn, pjlab.org.cn

I have an email from a French university @ens-paris-saclay.fr, do you know of any way to register this organization's suffix or any other alternative?


vendor: add gofail/runtime

to support FAILPOINTS=1 ./build with vendoring

/cc @heyitsanthony

@heyitsanthony You are right. Just fixed. PTAL. Thanks.

Anthony figured a way to fix gopath in build script. Closing. We can vendor later when we need gofail enabled tests in CI.


Retrieve notifications?

Does this project include the ability to retrieve one user's notifications?
I can see that we can tweak a lot of the notifications settings but I don't see where I can retrieve notifications. (but maybe I've missed it?)

I do not remember that it was implemented, but you can help the project

I tried analysing what happens when fetching notifications on Instagram website but I'm not really good at reverse-engineering APIs, so I'll pass on that. Thanks for your answer and I hope someone will have time to implement this!

If you use cl.news_inbox_v1() you can get them under new_stories and old_stories

If you use cl.news_inbox_v1() you can get them under new_stories and old_stories

Thank you @SinaKhalili, indeed this is where they are!


No longer building on Docker for Windows

Hey guys, love the project. looks like the latest bump caused it to stop building (for me anyway)
error:
npm ERR! Linux 4.4.20-moby
npm ERR! argv "/usr/bin/node" "/usr/bin/npm" "install"
npm ERR! node v6.7.0
npm ERR! npm  v3.10.8
npm ERR! code EAI_AGAIN
npm ERR! errno EAI_AGAIN
npm ERR! syscall getaddrinfo
npm ERR! getaddrinfo EAI_AGAIN registry.npmjs.org:443
npm ERR!
npm ERR! If you need help, you may report this error at:
npm ERR!     https://github.com/npm/npm/issues
npm ERR! Please include the following file with any support request:
npm ERR!     /usr/src/app/npm-debug.log
docker info:
Runtimes: runc
Default Runtime: runc
Security Options: seccomp
Kernel Version: 4.4.20-moby
Operating System: Alpine Linux v3.4
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 1.92 GiB
Name: moby

update: fix title

appears to be fixed now! thanks.


Only send checkbox/radio values for remote validation if checked

Doing remote validation for a checkbox value always sends the input's value whether the checkbox is checked or not and since the value is set to "true" for checkboxes the value will always be true on the server side even if you unchecked the checkbox when the remote validation was triggered. This change fixes this by only sending the value if the checkbox was checked. This is similar to what jquery-validation-unobtrusive does to handle remote checkbox validation.
I also added radio buttons to the check but I don't think it will work correctly for them since there will be multiple inputs with the same name selector for radio buttons but only the first one is handled which might not be the one that is clicked. So I'm not sure what the correct approach is for remote validation of radio buttons but this at least seems to be more in line with how jquery-validation-unobtrusive handles them.

Thanks for the contribution @davidkarlsson! I'll have it published soon!


Upgrade Dependencies

MySql, PostgreSql

We don't have to change these in yessql, we can do it directly in OC by adding a reference.

The build is still failing but I don't know how to fix it.
I may be should have let the references as they were in YesSql.Samples.Performance.csproj.

It's working for me.


Isis adj

Hi,
Please check new PR req for 548.
Thanks,
Prabha

Pull Request Test Coverage Report for Build<PHONE_NUMBER>

0 of 0   changed or added relevant lines in 0 files are covered.
No unchanged relevant lines lost coverage.
Overall coverage remained the same at 72.664%

Totals

Change from base Build<PHONE_NUMBER>:
0.0%

Covered Lines:
1462

Relevant Lines:
2012

💛  - Coveralls

/gcbrun

/gcbrun

Rebased to main to fix featureprofiles check!

Hi Likai,
Please could you help to merge this PR request.
@Ankur19 has reviewed and provided review and approval.
Thanks,
Prabha


Add dump_directory to dbpatch config

Add 'dump_directory' config setting to the dbpatch config, so when you call dbpatch dump all the dump files will be placed in the given directory.

Fixed in development branch


Set newly created filters as LastFilter, update results accordingly

Fixes #61
When a new filter is created, sets it as the active filter and updates the Task List.

@cheshire137 I have addressed the comments and added a test for the NewFilter submit button!


About ByteBuf.internalNioBuffer

Hi guys,
Why  ChannelOutboundBuffer.nioBuffers() use internalNioBuffer instead of nioBuffer ?
If i have a DIRECT byteBuf to write to two channels, and i forgot to slice or duplicate when write, because of the using of internalNioBuffer, the two channels (or two channel's eventloops) use the SAME ByteBuf's ByteBuffer, this will cause many problems.
E.g.
When the first eventLoop thread try to write the ByteBuf to socket but not start, and then, the second eventLoop thread start write the same ByteBuf and succeed, and then the first eventLoop thread resume, but when it write, the ByteBuf's ByteBuffer has no writable bytes, because the second eventLoop thread has already written it.
Now, for the first eventLoop thread, the ByteBuf's readerIndex is unmodified, so it think the ByteBuf has writable bytes, but the ByteBuf's ByteBuffer's position already reach it's limit, no writables bytes, so the eventLoop thread will try to write the ByteBuf, but write nothing, and then try again, and then write nothing, enter an endless loop...

@wangyuntao its to reduce object allocation.

@normanmaurer , thank you for your reply!
But if using internalNioBuffer, there's a chance to lead to EventLoop thread enter endless loop, is't too dangerous ?
After I‘v read the code, I have another question.
If I write a HeapByteBuf, netty will copy it to a DirectByteBuf, and if I write a DirectByteBuf, netty will use it,
then netty will write these DirectByteBufs to socket.
In this process, internalNioBuffer will be used in some setBytes methods, e.g. this, but why these setBytes methods use internalNioBuffer method instead of using buffer directly ? Perhaps for DirectByteBuf, internalNioBuffer method should return buffer instead of the cached one ? Perhaps for DirectByteBuf, the cached one is unnecessary ?
Is there something I'm missed or wrong ?


rustup; less strict timing tests

@bors r+

:pushpin: Commit 915d091973214c4379409fed7ed36b26c9d7750a has been approved by RalfJung

:hourglass: Testing commit 915d091973214c4379409fed7ed36b26c9d7750a with merge 1499c5a4d99c39326bd4a5ce5fcb419292296576...

:sunny: Test successful - checks-actions
Approved by: RalfJung
Pushing 1499c5a4d99c39326bd4a5ce5fcb419292296576 to master...


Update README to add citation section

Summary
Add Authors and Citation section to README.
Details and comments
Fixes #

Pull Request Test Coverage Report for Build<PHONE_NUMBER>
Details

0 of 0   changed or added relevant lines in 0 files are covered.
No unchanged relevant lines lost coverage.
Overall coverage remained the same at 82.354%

Totals

Change from base Build<PHONE_NUMBER>:
0.0%

Covered Lines:
6039

Relevant Lines:
7333

💛  - Coveralls


make this auto increment the  version number

Hi There-
I have a suggestion for a possible new feature that would be helpful to a lot of devs:
Would it be possible to get this action to have a property to increment the version number and display version number for us by 1
E.G
currently the action has these properties:
uses: managedcode/MAUIAppVersion@v1
with:
csproj: 'path/to/my-project.csproj'
version: ${{ github.run_number }} # to keep value unique
displayVersion: '1.0.0'
printFile: true # optional
add 2 new (optional) properties of :
incrementVersion: true
incrementDisplayVersion: Build
incrementDisplayVersion can have Major / Minor / Build  ( these correspond to which part of the version # to increase by one - eg in a display version they map to which position to increase by one in the version # eg 1.2.3  if I put build that is position 3 so version 1.2.3 would become 1.2.4)
incrementVersion: true  increases the Version # that is currently in the proj file by 1.
NOTE: when these increment options are specified then you dont need to supply a version or display version to the action as it will read the existing ones and increase them.
so we have:
uses: managedcode/MAUIAppVersion@v1
with:
csproj: 'path/to/my-project.csproj'
version: ${{ github.run_number }} # to keep value unique
displayVersion: '1.0.0'
printFile: true # optional
incrementVersion: true
incrementDisplayVersion: Build
This will increment the current Version # in minor position by 1  and also increase the buildDisplayVersion by 1.
By adding this it will make doing releases of new builds a lot more seamless rather than the dev having to manually work out version numbers.

Nice, I love this idea

One more thing - for incrementVersion: and incrementDisplayVersion can we also have a valid value of reuse.
What this would do is read the exisitng version and just reuse it (means i dont have to specify a version#).
What i am thinking is this:
In my comments when i check in i can add a tag of REUSE to rerun the build with the existing numbers without increasing them - this is for cases where the last build had failed with a error and i want to rerun it with the next commit.
So i would call it with these properties:
incrementVersion: reuse
incrementDisplayVersion: reuse
So if i want to do a build and increment the version #'s then i would use: (once again i would trigger these properties from a comment):
incrementVersion: true
incrementDisplayVersion: Build
This means the dev can decide to reuse the last increased version or increase them based on a check in comment.


Fix context disappearing across re-renders

Found another case where context can disappear.
  let Form = {
    render ({ props }) {
      return <div>{ props.visible ? <Button /> : [] }</div>
    }
  }

  let Button = {
    render ({ props, context }) {
      t.equal(context, 'the context', 'context is passed down')    💣💣💣
      return <button>Submit</button>
    }
  }

  let el = document.createElement('div')
  let render = createDOMRenderer(el)

  render(<Form visible={true} />, 'the context')
  render(<Form visible={false} />, 'the context')
  render(<Form visible={true} />, 'the context')
})

v2.0.0-rc6 makes context disappear on the 3rd render(). This fixes that.

Could you fix those lint errors in there? Then we can merge this one in :)

Sigh, you ain't gonna like this... this is standard's bias on React acting up, sorry for the eslint-disable :\

test/createDOMRenderer.js:140:27: 'visible' is missing in props validation (react/prop-types)

Standard insists there should be React.createClass({ propTypes: { ... } }), which isn't applicable in this case.

...rebased as well, there ya go. I'm off to sleep man, till next time and happy new year :)

Thanks! Happy new year. Thanks again for all your help on v2.


No longer silently fail if kudu is not installed.

Related to #742.

Thank you @isaacabraham for the fix! Merged.


RAINCATCH-655/658

#What
Bumped user module to apply https://github.com/feedhenry-raincatcher/raincatcher-user/pull/59
added placeholder banners to all users.
#Jiras
https://issues.jboss.org/browse/RAINCATCH-655
https://issues.jboss.org/browse/RAINCATCH-658

I'm guessing that the URL is pointing to your Fork for verification purposes only? Also, we may need to add a new access origin tag for Github too, since the images will be coming from here now.

Correct, will change it to the right one right after QA. Thought we re back to * access origin


COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS and COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS does not trigger related handlers in SimpleBasePlayer when using Media3 1.1.0

With Media3 1.0.0, we could handle cast device volume by implementing COMMAND_GET_DEVICE_VOLUME, COMMAND_SET_DEVICE_VOLUME and COMMAND_ADJUST_DEVICE_VOLUME commands in SimpleBasePlayer. We used cast API to get/set device volume. For implementation, see this and this. Here, RemoteDeviceVolumeProvider is a simple abstraction that deals with the cast API. As a result, we could adjust the cast device volume using volume rockers during an active cast session.
With Media3 1.1.0, the latter two commands are now deprecated in favour of COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS and COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS. However, when we replaced the deprecated commands with the new ones in our existing implementation, the SimpleBasePlayer stopped invoking handleSetDeviceVolume and other related handlers. As a result, nothing happens on pressing volume rockers during a cast playback session.
But if we continue using the deprecated commands, everything works as expected.
Is it a bug or an intended change? More importantly, how do we continue to use volume rockers to adjust cast device volume when the cast session is active while incorporating the latest changes?

Hi @ashutoshgngwr,
Could you confirm that you are now overriding the handler that has the following signature:
https://github.com/androidx/media/blob/5328d6464acb077a7e8cba61b8cac1973c4943d7/libraries/common/src/main/java/androidx/media3/common/SimpleBasePlayer.java#L3060-L3062
You can see that this is the handler that is triggered in both the new and deprecated methods in lines 2725 and 2738:
https://github.com/androidx/media/blob/5328d6464acb077a7e8cba61b8cac1973c4943d7/libraries/common/src/main/java/androidx/media3/common/SimpleBasePlayer.java#L2716-L2740

@oceanjules Hi there! Yes, I did implement the updated handlers (with flags). Moreover, the updated handlers appear to be working with deprecated commands but not with their replacements. Let me try to reproduce this in a minimal setting.

@oceanjules Here's a minimal Android project demonstrating this issue. If you uncomment these lines, you see log entries for the handlers in question on running the app and pressing volume rockers on the device. But handlers don't get invoked on commenting out the deprecated commands.

We also have a test that should check this behaviour (that also currently works) which you can use as a template for your minimal example:
https://github.com/androidx/media/blob/5328d6464acb077a7e8cba61b8cac1973c4943d7/libraries/common/src/test/java/androidx/media3/common/SimpleBasePlayerTest.java#L3183-L3218

We also have a test that should check this behaviour (that also currently works)

Couldn't that imply that the problem might be somewhere else?

which you can use as a template for your minimal example

Why?

Having tried your minimal example, I can only see this through logcat:
MediaSessionRecord      system_server     D  No routing session for com.example.myapplication
MediaSessionService     system_server     D  Adjusting suggestedStream=-2147483648 by 0. flags=4116, preferSuggestedStream=false, session=null

which comes from the MediaSessionRecord's "canHandleVolumeKey". I guess because isPlaybackTypeLocal() is false.
Setting the device info type to Local, gives us:
MediaSessionService     system_server D  dispatchVolumeKeyEvent, pkg=com.example.myapplication, opPkg=com.example.myapplication, pid=27424, uid=10316, asSystem=true, event=KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_VOLUME_DOWN, scanCode=114, metaState=0, flags=0x8, repeatCount=0, eventTime=434166456228000, downTime=434166456228000, deviceId=2, source=0x101, displayId=-1 }, stream=-2147483648, musicOnly=false
MediaSessionService     system_server D  Adjusting com.example.myapplication/androidx.media3.session.id.Playback (userId=0) by -1. flags=4113, suggestedStream=-2147483648, preferSuggestedStream=false

So I think all these key events are not going through Exoplayer at all, which is why I am not sure how you managed to get those log statement in the handlers working with the provided minimal setup.

I am getting the following logs when running my example on an Android 11 (actual device) with the remote device type.
MediaSessionService     dispatchVolumeKeyEvent, pkg=com.example.myapplication, opPkg=com.example.myapplication, pid=13269, uid=10377, asSystem=true, event=KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_VOLUME_DOWN, scanCode=114, metaState=0, flags=0x8, repeatCount=0, eventTime=43458071, downTime=43458071, deviceId=5, source=0x101, displayId=-1 }, stream=-2147483648, musicOnly=false
MediaSessionService     Adjusting com.example.myapplication/androidx.media3.session.id.Playback (userId=0) by -1. flags=4113, suggestedStream=-2147483648, preferSuggestedStream=false
MediaSessionService     dispatchVolumeKeyEvent, pkg=com.example.myapplication, opPkg=com.example.myapplication, pid=13269, uid=10377, asSystem=true, event=KeyEvent { action=ACTION_UP, keyCode=KEYCODE_VOLUME_DOWN, scanCode=114, metaState=0, flags=0x8, repeatCount=0, eventTime=43458200, downTime=43458071, deviceId=5, source=0x101, displayId=-1 }, stream=-2147483648, musicOnly=false
MediaSessionService     Adjusting com.example.myapplication/androidx.media3.session.id.Playback (userId=0) by 0. flags=4116, suggestedStream=-2147483648, preferSuggestedStream=false

If I replace *_WITH_FLAGS commands with their deprecated counterparts, I am getting the following.
MediaSessionService     dispatchVolumeKeyEvent, pkg=com.example.myapplication, opPkg=com.example.myapplication, pid=13986, uid=10377, asSystem=true, event=KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_VOLUME_UP, scanCode=115, metaState=0, flags=0x8, repeatCount=0, eventTime=43798183, downTime=43798183, deviceId=2, source=0x101, displayId=-1 }, stream=-2147483648, musicOnly=false
MediaSessionService     Adjusting com.example.myapplication/androidx.media3.session.id.Playback (userId=0) by 1. flags=4113, suggestedStream=-2147483648, preferSuggestedStream=false
MediaSessionPlayer      handleIncreaseDeviceVolume: flags=1
MediaSessionService     dispatchVolumeKeyEvent, pkg=com.example.myapplication, opPkg=com.example.myapplication, pid=13986, uid=10377, asSystem=true, event=KeyEvent { action=ACTION_UP, keyCode=KEYCODE_VOLUME_UP, scanCode=115, metaState=0, flags=0x8, repeatCount=0, eventTime=43798360, downTime=43798183, deviceId=2, source=0x101, displayId=-1 }, stream=-2147483648, musicOnly=false
MediaSessionService     Adjusting com.example.myapplication/androidx.media3.session.id.Playback (userId=0) by 0. flags=4116, suggestedStream=-2147483648, preferSuggestedStream=false
MediaSessionService     dispatchVolumeKeyEvent, pkg=com.example.myapplication, opPkg=com.example.myapplication, pid=13986, uid=10377, asSystem=true, event=KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_VOLUME_DOWN, scanCode=114, metaState=0, flags=0x8, repeatCount=0, eventTime=43798951, downTime=43798951, deviceId=5, source=0x101, displayId=-1 }, stream=-2147483648, musicOnly=false
MediaSessionService     Adjusting com.example.myapplication/androidx.media3.session.id.Playback (userId=0) by -1. flags=4113, suggestedStream=-2147483648, preferSuggestedStream=false
MediaSessionPlayer      handleDecreaseDeviceVolume: flags=1
MediaSessionService     dispatchVolumeKeyEvent, pkg=com.example.myapplication, opPkg=com.example.myapplication, pid=13986, uid=10377, asSystem=true, event=KeyEvent { action=ACTION_UP, keyCode=KEYCODE_VOLUME_DOWN, scanCode=114, metaState=0, flags=0x8, repeatCount=0, eventTime=43799132, downTime=43798951, deviceId=5, source=0x101, displayId=-1 }, stream=-2147483648, musicOnly=false
MediaSessionService     Adjusting com.example.myapplication/androidx.media3.session.id.Playback (userId=0) by 0. flags=4116, suggestedStream=-2147483648, preferSuggestedStream=false
MediaSessionService     dispatchVolumeKeyEvent, pkg=com.example.myapplication, opPkg=com.example.myapplication, pid=13986, uid=10377, asSystem=true, event=KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_VOLUME_UP, scanCode=115, metaState=0, flags=0x8, repeatCount=0, eventTime=43799771, downTime=43799771, deviceId=2, source=0x101, displayId=-1 }, stream=-2147483648, musicOnly=false
MediaSessionService     Adjusting com.example.myapplication/androidx.media3.session.id.Playback (userId=0) by 1. flags=4113, suggestedStream=-2147483648, preferSuggestedStream=false
MediaSessionPlayer      handleIncreaseDeviceVolume: flags=1
MediaSessionService     dispatchVolumeKeyEvent, pkg=com.example.myapplication, opPkg=com.example.myapplication, pid=13986, uid=10377, asSystem=true, event=KeyEvent { action=ACTION_UP, keyCode=KEYCODE_VOLUME_UP, scanCode=115, metaState=0, flags=0x8, repeatCount=0, eventTime=43799950, downTime=43799771, deviceId=2, source=0x101, displayId=-1 }, stream=-2147483648, musicOnly=false
MediaSessionService     Adjusting com.example.myapplication/androidx.media3.session.id.Playback (userId=0) by 0. flags=4116, suggestedStream=-2147483648, preferSuggestedStream=false

I am not getting any entries with the MediaSessionRecord tag. Now I am not aware of how the internals work in the framework, but I think this should add some clarity.

Hi @ashutoshgngwr,
Thank you for providing the Android version, that was the key piece of information that helped me reproduce it.
I have found the issue and we will be patching up a bugfix for it. For reference, these if-statements, should have had the new commands as well. Otherwise, the volumeControlType was set as FIXED, i.e. not changeable
https://github.com/androidx/media/blob/5328d6464acb077a7e8cba61b8cac1973c4943d7/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java#L1032-L1037
Also for reference, the reason it didn't work for me was because I was testing with Android 12 and 13 and it's a known issue that the hardware buttons and volume of a cast device are currently not working:
https://issuetracker.google.com/issues/201546605


HMC: add reject function.

The HMC family samplers occasionally runs into regions with 0 density. It is helpful to be able to reject and restart the current Hamiltonian simulation when this happens.

@xukai92 can you add the reject step for NUTS and eNUTS?

Sure. Do you want me to do that in the current PR?

Yes, let's push to the same PR.

[ ] Merge eNUTS and NUTS
[ ] Implement reject for NUTS.

The current leapfrog code either returns a new simulation with total trajectory length (τ * ϵ), or reject the whole simulation.
leapfrog(_vi, _p, τ, ϵ, model, spl)

Instead of simply rejecting a (whole) simulation, perhaps we should improve the leapfrog function, so that partial valid simulation (e.g. trajectory_length <=  τ * ϵcan be returned.


MQTT Certificates

Hey, when do you plan to implement the certificates for MQTT?
https://github.com/esp-rs/esp-idf-svc/blob/master/src/mqtt/client.rs#L76
// TODO: Future

// pub cert_pem: &'a [u8],
// pub client_cert_pem: &'a [u8],
// pub client_key_pem: &'a [u8],

Do you have any suggested workaround to use them?

Ideally, whoever needs them should open a PR with the changes. :) For example, you might volunteer, and then the whole community would benefit.

I'm already trying to :P

Fixed.


SelectAll fails to do anything when there's only one line

SetSelection(Coordinates(0, 0), Coordinates((int)mLines.size(), 0));
Would resolve to Coordinates(0,0), Coordinates(1,0), which is then sanitised by SetSelection to Coordinates(0,0),Coordinates(0,0), resulting in no selection as the end coord is beyond the end of the document.
I've fixed this locally by changing it to select the last character of the last line instead of the line beyond the end of the document:
void TextEditor::SelectAll()
{
	if(!mLines.empty())
		SetSelection(Coordinates(0, 0), Coordinates((int)mLines.size()-1, mLines.back().size()));
}

Fixed now, please test. Actually SanitizeCoordinates was the culprit, setting the column to zero if the input was pointing beyond the end of the text.


Issue tracking has moved.

Please send new comments and bug reports to https://support.unpaywall.org or<EMAIL_ADDRESS>Thanks!
Existing issues have been closed and moved as appropriate.

@richard-orr, this should be in the readme, and issues should be disabled, then. However, note that I believe this decision to be foolish. Additionally, many issues remain open.


[CRITICAL] [UX Reliability] Sometimes new users has 2 concierge chats after first sign up

If you haven’t already, check out our contributing guidelines for onboarding and email<EMAIL_ADDRESS>to request to join our Slack channel!

Version Number: 1.4.75-1
Reproducible in staging?:
Reproducible in production?:
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
Issue reported by:
Slack conversation: https://expensify.slack.com/archives/C05LX9D6E07/p1717178036627669?thread_ts=1716934948.607449&cid=C05LX9D6E07
Time of bug report: 2024-05-28 3:22pm PDT
Action Performed:
Break down in numbered steps

As Alice request money from user that does not have account yet (Bob)

As Bob, you will receive an email with this request

Click Pay and verify you are redirected to the login screen

Log in as Bob

Check out chats in the LHN

Expected Result:
Describe what you think should've happened
There should only be one Concierge chat
Actual Result:
Describe what actually happened
There are two chats that we essentially concierge chat. One of them however looks weird like this

Workaround:
Can the user still use Expensify without this being fixed? Have you informed them of the workaround?
Platforms:

Which of our officially supported platforms is this issue occurring on?

[ ] Android: Native
[ ] Android: mWeb Chrome
[ ] iOS: Native
[ ] iOS: mWeb Safari
[ ] MacOS: Chrome / Safari
[ ] MacOS: Desktop

Screenshots/Videos
Add any screenshot/video evidence

View all open jobs on GitHub
Issue OwnerCurrent Issue Owner: @neil-marcellini

Adding to newdot-quality
Noting that this might be a race condition, so it's not always reproducible. It seems like the odd chat might be created optimistically, and we get the correct concierge chat later in the OpenApp response. This needs to be investigated

This has been labelled "Needs Reproduction". Follow the steps here: https://stackoverflowteams.com/c/expensify/questions/16989

hey @mountiny I'm wondering if this might be the same root? - https://github.com/Expensify/App/issues/42321
I tried to reproduce this through these steps;

As<EMAIL_ADDRESS>request money from user that does not have account yet<EMAIL_ADDRESS>As<EMAIL_ADDRESS>you will receive an email with this request (I'm not getting this)
Log in as<EMAIL_ADDRESS>Check out chats in the LHN

I'm not getting any email... I wonder if this needs to be tested in dev?

I think this is specific about the Concierge chat being duplicated

Hey there, I'm jumping in to help investigate this internally.

First I tried testing a very simple case on dev to see if I could reproduce the error. I used these steps.

Log in with an existing account A
Submit a manual expense to a new account B
Log in as account B
Check the LHN

The concierge chat appeared fine, so next I'll test with the exact steps in the description. I think it was helpful to rule out the simple case first.

I'm unable to reproduce the error on dev following the exact flow described.

@neil-marcellini I have just reproed locally something weird potentially related.

Create account in oldDot for new account which was never used before
Sign into the same account in NewDot
There was some weird chat I was navigated to

I was not able to repro again though, really odd, not sure what is causing this

The thread where we're discussing this now is here.
The reportIDs of the concierge chat with two users, and with only concierge, are these values respectively<PHONE_NUMBER>067399,<PHONE_NUMBER>117393.
I extracted that from the video @danielrvidal shared.
As Puneet suggested, I'm going to determine if these chats actually exist in the DB or if they are optimistic. I'll try with supportal first, then maybe request CQs if that fails. The email of the account is<EMAIL_ADDRESS>

For the concierge chat report which included the current account<PHONE_NUMBER>067399, I get that the report was not found. Therefore it was an optimistic report.

For the other report<PHONE_NUMBER>117393, I get a response suggesting that the report actually exists, although OldDot shows an endless spinner, but that's probably just because OldDot doesn't load chat reports properly.

Here is the response
{
    "jsonCode": 200,
    "reports": {
        "6655774248117393": {
            "accountEmail": "__fake__",
            "accountID": 0,
            "approved": "",
            "cachedData": "",
            "cachedTotal": "$0.00",
            "created": "2024-05-28 22:16:42",
            "currency": "USD",
            "entryID": "",
            "isStatementReport": false,
            "managerEmail": "__fake__",
            "managerID": 0,
            "orderDealNumbers": "",
            "reportID":<PHONE_NUMBER>117393,
            "reportName": "Chat Report",
            "reportStatus": 0,
            "starred": false,
            "state": "OPEN",
            "stateNum": 0,
            "status": 0,
            "submitted": "",
            "transactionCount": 0,
            "transactionList": [],
            "reportNameValuePairs": {
                "expensify_policyID": "_FAKE_",
                "lastReadTime_17304561": "2024-05-28 22:16:42.359",
                "type": "chat"
            },
            "reportActionList": [
                {
                    "accountEmail": "__fake__",
                    "accountID": "0",
                    "action": "CREATED",
                    "created": "2024-05-28 22:16:42.358",
                    "message": {
                        "creatorAccountID": 17304561,
                        "lastModified": "2024-05-28 22:16:42.358"
                    },
                    "previousReportActionID": "0",
                    "reportActionID": "6162605927137434213",
                    "reportID":<PHONE_NUMBER>117393,
                    "sequenceNumber": 0
                },
                {
                    "accountEmail"<EMAIL_ADDRESS>                    "accountID": "8392101",
                    "action": "ADDCOMMENT",
                    "created": "2024-05-28 22:16:43.452",
                    "message": {
                        "html": "
Welcome to Expensify<\/h1>\ud83d\udc4b Hey there, I'm Concierge! If you have any questions about Expensify, you can always chat with me here 24-7 for fast and reliable support. I'm happy to help!",
                        "lastModified": "2024-05-28 22:16:43.452"
                    },
                    "previousReportActionID": "6162605927137434213",
                    "reportActionID": "5027620404823866902",
                    "reportID":<PHONE_NUMBER>117393,
                    "sequenceNumber": 1
                },
                {
                    "accountEmail"<EMAIL_ADDRESS>                    "accountID": "8392101",
                    "action": "ADDCOMMENT",
                    "created": "2024-05-30 08:29:33.160",
                    "message": {
                        "html": "
What will you use Expensify for?<\/h1>Choose the features you need and I can help get you up and running here.<\/a> For questions, just reply to this message or request a call<\/a>.",
                        "isMarketingMessage": true,
                        "lastModified": "2024-05-30 08:29:33.160"
                    },
                    "previousReportActionID": "5027620404823866902",
                    "reportActionID": "3884547479339066364",
                    "reportID":<PHONE_NUMBER>117393,
                    "sequenceNumber": 2
                }
            ],
            "sharedReportList": [
                {
                    "accountID": 17304561,
                    "email"<EMAIL_ADDRESS>                    "permissions": "read, write"
                },
                {
                    "accountID": 8392101,
                    "email"<EMAIL_ADDRESS>                    "permissions": "read, write"
                }
            ],
            "publicRoomActors": [],
            "mentionedReportsDetails": [],
            "mentionedAccountsPersonalDetails": [],
            "fieldList": [],
            "comments": [],
            "showChart": false,
            "formattedTotal": "$0.00",
            "starting": "2027-08-02",
            "ending": "1970-01-01",
            "editable": true,
            "ownerEmail": "__fake__",
            "ownerAccountID": 0,
            "lastVisibleActionCreated": "2024-05-30 08:29:33.160",
            "lastReadTime": "2024-05-28 22:16:42.359",
            "violations": [],
            "nextStep": {
                "buttons": [],
                "message": [
                    {
                        "text": "Waiting for "
                    },
                    {
                        "text": "__fake__",
                        "type": "strong",
                        "tooltipText": "__fake__ (click to copy)",
                        "clickToCopyText": "__fake__"
                    },
                    {
                        "text": " to "
                    },
                    {
                        "text": "add expenses",
                        "type": "strong"
                    },
                    {
                        "text": " to this report."
                    }
                ],
                "title": "Next Step:",
                "requiresUserAction": false,
                "type": null,
                "showUndoSubmit": false,
                "showForMobile": true,
                "showForExpense": true,
                "expenseMessage": [],
                "nextReceiver": ""
            }
        }
    },
    "globals": {
        "csrfToken": "nem9+RNPHk7UfMiVirxeV4BJOXw8l5SdVPCfSOzRdloZypC9kG7uMvqyOg5wr4Sg7J\/m1EZQMKu4+NoOHh3Sa4Ftjdu8\/\/DLeIdHzTrnDXX\/NBmcJ34HzkvPsqleWbQKmu4HeTrjaMajoHo0aCeC9KpSCPJF\/eRZEshBbJEM"
    },
    "codeRevision": "eb1b5ef0cef7d0ef467cd0405232442f7958889e",
    "requestID": "88caa0720bcaf9f9-SJC"
}

I will continue my investigation by looking at how an optimistic concierge chat report might get created.

I think this is where the optimistic concierge chat could be coming from, but I need to dig deeper to determine how things might go wrong. Definitely seems like some kind of a race condition. I ran out of time for today.

Hello, I'm Jakub from the Software Mansion expert's agency. I've been trying to reproduce an issue, but I'm not receiving any emails when requesting money (splitting an expense). I've attempted this with 2 different email accounts and waited over 15 minutes. I'm not sure if this is a problem with my email account or with outgoing Expensify emails (magic code emails are working fine for me).
I will try again later, as I cannot proceed without this email.

Hi Jakub, I also experienced the same issue when trying to reproduce on staging. I'll test once more today and if I don't get an email I will create a separate backend issue to investigate that.

I'm going to write out the entire frontend flow relating to concierge chats.
The first thing to look at is where are optimistic concierge chats created?
Optimistic chat reports are created with the function buildOptimisticChatReport.
That function is used in many places, but only navigateToAndOpenReport is relevant
It's used by navigateToConciergeChat
That's called from the Concierge page
It's part of the AuthScreens, so it will only show after the user has logged in
The call in the Concierge page runs in a focus effect, which runs when the component is mounted and focused
If the navigation is ready and the component is still mounted, then the function is called
Within navigateToConciergeChat it checks if the conciergeChatReportID is unset, and if so calls onServerDataReady with a callback.
onServerDataReady just returns the isServerDataReadyPromise, which is tied to the value of resolveIsReadyPromise, which is called by checkServerDataReady when ONYXKEYS.IS_LOADING_REPORT_DATA is updated with the value false.
Shoot, so after testing, I see that the Concierge page only mounts if you navigate to https://dev.new.expensify.com:8082/concierge, and it doesn't happen in this flow.
I looked at the other uses of navigateToConciergeChat and they don't look promising. Not sure what do do here. Maybe I can get logs for the actual flow in the bug report?

Aha, I found App logs from the bug report video.
The report that the pay button navigates to is reportID<PHONE_NUMBER>763561.
I'm still lost on this one though, so maybe I should look carefully at the flow which happens when you navigate to a report while logged out. It kind of looks like the report was in Onyx before he even signed in, because it loads surprisingly fast.
I think it would be easy to waste a lot of time on this, so I'm suggesting in Slack that we close or hold this and focus on why we can't get emails for new chats.

Closing this out since it's not reproducible and we don't really have any leads on how to solve it. One thing we did learn is that emails for new money requests are not sent to expensifail users.


Failures in Isolate::ValidateConstants()

dartkb-mixed-linux-debug-x64:standalone_2/io/http_advanced_test
dartkb-mixed-linux-debug-x64:standalone_2/io/http_basic_test
dartkb-mixed-linux-debug-x64:standalone_2/io/socket_close_test
These failures begin with https://dart-review.googlesource.com/c/sdk/+/95491/, but seem to be timing related rather than field-guard related since they stop reproducing at -O1 and -O0.

https://dart.googlesource.com/sdk/+/217a0274568e14416e6ddb1d1692efe5b0896766


Adding more GA events now that client-side validation is set up.

What's this PR do?
This PR adds a few event subscribers, like in Phoenix, so we can send some Google Analytics events off when these events happen.
How should this be reviewed?
👀
Checklist

[ ] Tests added for new features/bug fixes.

For review:
@angaither @sbsmith86
cc: @jessleenyc

looks ok to me!

thanks @sbsmith86!


RFC: process.env.RAZZLE_RUNTIME_XXXX

Current Behavior
People struggle with how Razzle deals with .env variables (i.e. stringifying them at build time by webpack) just like create-react-app.
Expected Behavior
Razzle should have a way to honor runtime variables so users can more easily deploy their apps to Now/Heroku/Azure etc.
Suggested Solution
Make PORT, HOST, and any other env variables prefixed with RAZZLE_RUNTIME_XXXXXXX available during runtime.
Before
Available at compile time (i.e. will be stringified by webpack)

RAZZLE_XXXXXX
PORT
HOST

After
Available at runtime

PORT
HOST
RAZZLE_RUNTIME_XXXXXXX

Available at compile time (i.e. will be stringified by webpack)

RAZZLE_XXXXXX

Discussion
Another alternative is to only stringify variables prefixed with RAZZLE_XXXX like the razzle-heroku plugin does. This would also be backwards compatible too. On the one hand, this would make it easier to work with how Heroku names it's config environment variables (e.g. MONGO_URI). On the other hand, this would be too easy to mess up by accident (i.e. reference a runtime variable within shared isomorphic code that is undefined on the client...exploding the application).
Related
#527 #526 #514 #477 #356 #285

I personally wouldn't worry too much about process.env being unavailable on the client. We already have to know that 'window' is unavailable on the server; it makes sense to me that process.env would have the opposite behavior. (there's no node process to have an env for, and browsers don't expose their env vars that I'm aware of) I think of process.env as a place where server secrets can end up, so I'd rather it was unavailable on the client-side by default.
If it were up to me, process.env.RAZZLE_INLINED_XXXXXX variables would get compiled in during the build, (and available on the client as inline DefinePlugin'd strings) and anything else would only be available on the server-side.
NODE_ENV could be inlined too, as it's mostly used as a description of the build and not something variable like the environment that the code is running in. There are also some performance reasons to do so.
I do like the idea of PORT and HOST being variable at runtime. I may be running the same build artifacts in different environments.

I can confirm the struggle. The current behaviour was not what I expected and especially tripped me up when deploying with up on aws. I have now customized the razzle.config.js so that all razzle specific vars are prefixed with RAZZLE_XXX and those are stringified at compile time. The rest ist available on process.env.XXX. I also agree with @gregmartyn about the unavailability of runtime vars through process.env.

While trying to set Razzle up in an existing React project we faced this issue. The port isn't overridable at run-time, and other process.env variables aren't available in the server.
Current behaviour at build-time:
process.env.PORT
process.env.NODE_ENV;
process.env.ASSETS_MANIFEST;
process.env.HOSTING_SET_VARIABLE;

becomes on both client and server:
3000;
'development';
'/Users/[...]/build/assets.json';
undefined;

While this assures that client and server can use exactly the same process envs, this makes it impossible to override at runtime or use other environment variables.
If you want to fully be backwards compatible, it should be transpiled to this in build-time (on the server, client can stay the same):
process.env.PORT || 3000;
process.env.NODE_ENV || 'development';
process.env.ASSETS_MANIFEST || '/Users/[...]/build/assets.json';
process.env.HOSTING_SET_VARIABLE;

This way, you can use process.env.PORT in both the client and the server. It will default to 3000.
If razzle is built with PORT=80, the client have process.env.PORT transpiled to 80 and the server will have it transpiled to process.env.PORT || 80. This will result in the same behaviour as how it is now.
If razzle is run with PORT=81 (while built with 80), the clients environment variable will stay 80 while the server variable will result in 81.
This behaviour can of course lead to unexpected behaviour, but it does provide the most flexible usage of process.env while maintaining full backwards compatibility. The port can still be overwritten on the server at run-time, and other environment variables set by hosting platforms will work on the server as-is.

I think the underlying issue here is that Razzle is currently trying to pack multiple disparate functions into one object, and fundamentally change existing functionality.
It's trying to:

Turn process.env variables into constants for performance reasons (see minification example on https://webpack.js.org/plugins/define-plugin/#usage and nodejs slowness at https://github.com/nodejs/node/issues/3104)
Make those constants available to both the server and client so that isometric code has less to worry about.

Problems:

process.env is for environment variables. Turning it into a set of constants changes its expected behavior.
process.env often contains sensitive info including passwords, so it's not a great source for data to share with the client. If it's partially shared, and partially not shared, the dev must know that this one thing -- process.env -- not only doesn't behave like it does natively, but that it also has different behavior depending on the keys' prefixes.
It's being turned into constants at build time, which is different from how environment variables behave in other contexts. Docker, for example, makes a distinction between build-time variables (useful when the build itself requires variable info depending on where it's running) and environment variables (useful when one pre-built image is deployed to different environments). Elastic Beanstalk, Heroku, et al. do the same.
The suggested "RAZZLE_RUNTIME_" prefix isn't self-explanatory. It should convey that it's available client-side and that it's not a variable. I think "INLINED_" covers that, as inlining is commonly used to refer to something that happens at build time. It's not perfect, ("ISOMORPHIC_INLINED_"?) but it's also trying to be short.

My preference would be to split this functionality into different parts, and to not tamper with process.env at all.
The DefinePlugin could call out to a file like razzle.config.js to get the build constants
Recommend using a pattern similar to what Redux does with configureStore(window.PRELOADED_STATE) to pass data from server to client.
For backward compatibility, upgrade notes could provide a sample razzle.config.js that does the defines the old fashioned way.

One addendum: I said "to not tamper with process.env at all." but I could see there being an exception for process.env.NODE_ENV for the performance reasons from my comment above and that "NODE_ENV" itself has generally taken on the meaning of "NODE_ENV = production means that this is an optimized build"

@gregmartyn we have to set NODE_ENV for perf optimizations and to use babel preset as it works now. My initial reasoning for messing with env was to make moving from CRA much easier as SSR is often added after a project has already started. We also use CRA on other projects so it simplifies our build tooling (slightly).

I am reposting my proposed solution for an isomorphic react app from https://github.com/jaredpalmer/razzle/issues/477#issuecomment-363538712
The main concept is to use a placeholder at compile time that is injected at runtime just before server execution in order properly set runtime environment variables. This solution is for running the server in a docker container but could probably be adapted for this RFC.

I've personally struggled with this issue and spend several hours figuring out a solution to this issue.
This is inherent to webpack compilation and not related to razzle it self.
After looking into how create-react-app handles this, and porting some javascript and ruby code, across two projects, I've successfully deployed a razzle typescript react app in a docker container on heroku with the following solution:
env.ts
This script is used as a module to handle runtime env.
export interface EnvironmentStore {
  NODE_ENV?: string;
  [key: string]: string | undefined;
}

// Capture environment as module variable to allow testing.
let compileTimeEnv: EnvironmentStore;
try {
  compileTimeEnv = process.env as EnvironmentStore;
} catch (error) {
  compileTimeEnv = {};
  // tslint:disable-next-line no-console
  console.log(
    '`process.env` is not defined. ' +
    'Compile-time environment will be empty.'
  );
}

// This template tag should be rendered/replaced with the environment in production.
// Padded to 4KB so that the data can be inserted without offsetting character
// indexes of the bundle (avoids breaking source maps).
/* tslint:disable:max-line-length */
const runtimeEnv = '{{RAZZLE_VARS_AS_BASE64_JSON__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________}}';
/* tslint:enable:max-line-length */

// A function returning the runtime environment, so that
// JSON parsing & errors occur at runtime instead of load time.
export const loadRuntimeEnv = (): EnvironmentStore => {
  let env;
  if (typeof env === 'undefined') {
    if (compileTimeEnv.NODE_ENV === 'production') {
      try {
        env = JSON.parse((Buffer.from(runtimeEnv.trim(), 'base64').toString()));
      } catch (error) {
        env = {};
        const overflowsMessage = runtimeEnv.slice(32, 33) !== null;
        // tslint:disable-next-line no-console
        console.error(
          'Runtime env vars cannot be parsed. Content is `%s`',
          runtimeEnv.slice(0, 31) + (overflowsMessage ? '…' : '')
        );
      }

    } else {
      env = compileTimeEnv;
    }
  }
  return env;
};

export default loadRuntimeEnv;

usage:
import { loadRuntimeEnv, EnvironmentStore } from './env';
const env: EnvironmentStore = loadRuntimeEnv();

const serverHost: string =env.RAZZLE_SERVER_HOST || 'localhost';

docker-start.js
This script is used as the entrypoint point instead of server.js and is used to inject {{RAZZLE_VARS_AS_BASE64_JSON___... }} placehoder with the actual runtime environment variables.
require('newrelic');
const logger = require('heroku-logger');
const path = require('path');
const fs = require('fs');

const PLACEHOLDER = /\{\{RAZZLE_VARS_AS_BASE64_JSON_*?\}\}/;
const MATCHER = /^RAZZLE_/i;

const InjectableEnv = {

    inject: function(file, ...args) {

        const buffer = fs.readFileSync(file, { encoding: 'utf-8' });
        let injectee = buffer.toString();

        const matches = injectee.match(PLACEHOLDER);
        if (!matches) {
            return;
        }

        const placeholderSize = matches[0].length;

        let env = InjectableEnv.create(args);
        const envSize = env.length;
        const newPadding = placeholderSize - envSize;
        if (newPadding < 0) {
            console.log('You need to increase your placeholder size');
            process.exit();
        }
        const padding = Array(newPadding).join(' ');
        env = InjectableEnv.pad(padding, env);

        const injected = injectee.replace(PLACEHOLDER, env);

        fs.writeFileSync(file, injected, { encoding: 'utf-8' });
    },

    create: function() {

        const vars = Object.keys(process.env)
            .filter(key => MATCHER.test(key))
            .reduce((env, key) => {
                env[key] = process.env[key];
                return env;
            }, {});

        vars.NODE_ENV = process.env.NODE_ENV;

        if (typeof process.env.HOST !== 'undefined' && typeof vars.RAZZLE_SERVER_HOST === 'undefined') {
          vars.RAZZLE_SERVER_HOST = process.env.HOST;
        }

        if (typeof process.env.PORT !== 'undefined' && typeof vars.RAZZLE_SERVER_PORT === 'undefined') {
          vars.RAZZLE_SERVER_PORT = process.env.PORT;
        }

        if (typeof process.env.REDIS_URL !== 'undefined' && typeof vars.RAZZLE_REDIS_URL === 'undefined') {
          vars.RAZZLE_REDIS_URL = process.env.REDIS_URL;
        }

        return Buffer.from(JSON.stringify(vars)).toString('base64');
    },

    pad: function(pad, str, padLeft) {
        if (typeof str === 'undefined')
            return pad;
        if (padLeft) {
            return (pad + str).slice(-pad.length);
        } else {
            return (str + pad).substring(0, pad.length);
        }
    }
}

const root = process.cwd();
const serverBundle = path.resolve(path.join(root, '/build/server.js'));

if (fs.existsSync(serverBundle)) {
    logger.info('Injecting runtime env');
    InjectableEnv.inject(serverBundle);
    logger.info('Launching server instance');
    require(serverBundle);
}

Dockerfile
# You should always specify a full version here to ensure all of your developers
# are running the same version of Node.
FROM node:8.9.4

ENV NODE_ENV=production \
    REACT_BUNDLE_PATH=/static/js/vendor.js \
    PATH=/app/node_modules/.bin:$PATH \
    NPM_CONFIG_LOGLEVEL=warn

RUN curl -o- -L https://yarnpkg.com/install.sh | bash

# use changes to package.json to force Docker not to use the cache
# when we change our application's nodejs dependencies:
COPY package.json yarn.lock /tmp/
RUN cd /tmp \
  && yarn install --production=false --pure-lockfile \
  && mkdir -p /app \
  && cp -a /tmp/node_modules /app \
  && yarn cache clean \
  && rm -rf *.*

# From here we load our application's code in, therefore the previous docker
# "layer" thats been cached will be used if possible
WORKDIR /app
ADD . /app

RUN yarn build

EXPOSE 3000

CMD ["node", "docker-start.js"]

Please note that the overflow message processing is not finished, but I hope this helps

References:
Heroku Buildpack for create-react-app
Inner layer of Heroku Buildpack for create-react-app

This is inherent to webpack compilation and not related to razzle it self.

Razzle is the one setting up DefinePlugin. This is solvable in Razzle.
I think I follow what you're saying. Tell me if I got this wrong: At build time, put placeholders into process.env that get string replaced on instance startup in the server build. It's meant to handle server secrets. (I don't see why it couldn't run on the client build too though) Problems: It won't work with HMR. It's a hack -- it introduces an arbitrary 4k boundary. In its current form, it doesn't address env vars that have to be shared with the client -- those remain build-time constants. It's an extra startup step for containers.
To rehash a lot of what I said in https://github.com/jaredpalmer/razzle/issues/528#issuecomment-377058844
I think the solution is to recognize that Razzle and CRA are trying to pack more functionality into process.env than it should have. To get it to work with Docker, we're trying to have one object with fields having one of 4 possible states: static (build time) and dynamic (here, container start time), secrets and non-secrets. We could come up with prefixes for all 4 of those states (process.env.STATIC_PRIVATE_X, process.env.DYNAMIC_PUBLIC_Y, ...) but I think we'd be much better off with a cleaner solution.
If process.env were to behave the way it does natively -- as a store of server secrets -- then things are a lot easier to understand. There's one exception: NODE_ENV as a build-time inline, but that's fine because it's a property of the build. It wouldn't make sense to set NODE_ENV at runtime.
All that's left is a way to get data to the client. I don't see why this is using process.env at all. Why not use e.g. razzle.build.X for static stuff, and pass dynamic stuff to the client the same way redux does?
There's another issue where process.env is slow on Node, but that's best addressed with a cache layer that reads process.env once.

@gregmartyn I agree that this is a hack ... and It does introduce an arbitrary 4K boundary. This idea is based on what is currently done with CRA (see the posted references) and is intended for server side runtime env variables.

Opened a PR that I believe should help with this root of this issue - env vars not being available on the server at runtime, interested to hear if this solves some of the issues here.
I also agree that PORT & HOST would also ideally be left alone at server compile time.

@tgriesser nice! That is a big improvement.
In addition to PORT and HOST, I'd add PUBLIC_PATH to the list of vars that shouldn't be compiled in.

I am still finding sensitive custom environment variables are all being compiled into the client. I am referencing them only in server.js. Does razzle consider that isomorphic because of the hotloader? How can I prevent these from reaching the client.

Hey everyone, I am tackling all of this at work this week. Stay tuned. #611 is likely to get merged.

Following the new guide in the readme with config.js worked for me with regards to removing sensitive env variables from the bundle. Awesome :D

See v2 notes

@jaredpalmer I might be missing something, but this is still an issue for things like PORT, despite what the readme docs imply. process.env.MY_THING works fine, but process.env.PORT is still replaced at build time and are not read at runtime. So the Heroku example doesn't actually work.
I don't see any special handling of PORT, HOST, etc as discussed in this thread.

Can someone please advise how to deploy Razzle app on Azure? I am really struggling with it.

if anyone want to use .env variables in runtime, use this little package.
https://www.npmjs.com/package/razzle-plugin-runtimeenv

How does it work? Could you show an example?
I think environment variables should be injected at runtime indeed. If we conteinerize a razzle app, we would like to create an image independently of the environment it runs, and read the environment variables on starting the server and serve them to the client app then.
Any other approach is not really using environment variables since it's happening only during build time.

As i mentioned here:
https://github.com/HamidTanhaei/razzle-plugin-runtime/issues/1#issuecomment-525731273
you can use your .env and .env.development files in the runtime by razzle-plugin-runtime. it adds ability to use your env variables in your app in runtime.
for example i'm using it to config axios:
axios.defaults.baseURL = ${process.env.RAZZLE_APP_API_BASE_PATH}${process.env.RAZZLE_APP_API_VERSION};
and you can provide production ENV variables for production like this:
https://github.com/jaredpalmer/razzle#adding-temporary-environment-variables-in-your-shell

Can someone please advise how to deploy Razzle app on Azure? I am really struggling with it.

I resolved the Azure Port issue using the solution shared by @fabianishere  at https://github.com/jaredpalmer/razzle/issues/906#issuecomment-467046269


ld error compiling hello world on OpenBSD (hacky temporary fix included)

I put the following (from here) in f.aum:
module body Hello is
    function main(): ExitCode is
        printLn("Hello, world!");
        return ExitSuccess();
    end;
end module body.

and run  path/to/austral compile f.aum --entrypoint=Hello:main --output=hello (EDITED: the original version of this report had the wrong command there) and see a bunch of errors, included at the bottom of this message. I'm running OpenBSD-current on amd64.
It looks like they're all warnings except that ld can't find stdin or stdout. The following patch (against master, commit 260311b21e6) (EDITED: the patch in the original version of this report had an accidental extra silly change) fixes it so the hello world program compiles and works:
diff /home/falsifian/co/austral
commit - 260311b21e6150d606d21c7195a5d06a6a8cd652
path + /home/falsifian/co/austral
blob - b1811944ace1d52ade70ffefb068f4dc5202475e
file + lib/prelude.c
--- lib/prelude.c
+++ lib/prelude.c
@@ -57,6 +57,9 @@ void* au_stdout() {
 #if defined(__APPLE__)
   extern void* __stdoutp;
   return __stdoutp;
+#elif defined(__OpenBSD__)
+  extern void *__sF;
+  return &__sF[1];
 #else
   extern void* stdout;
   return stdout;
@@ -83,6 +86,9 @@ extern void* au_stdin() {
 #if defined(__APPLE__)
   extern void* __stdinp;
   return __stdinp;
+#elif defined(__OpenBSD__)
+  extern void *__sF;
+  return &__sF[0];
 #else
   extern void* stdin;
   return stdin;

However, I expect this will only work until the next time the OpenBSD devs change the internals. I'm curious, why not write normal portable C code, with #include <stdio.h> etc? What I see in prelude.c seems to be just asking for trouble. If you like, I can try to draft a patch that does that.
Here's the promised error output:
Error:
  Title: Command Line Arguments Error
  Module:
    [unknown]
  Location:
    [no span available]
  Description:
    Failed to run C compiler.

    Command: `cc /tmp/austral_69513e.c -fwrapv -lm -o hello`

    Exit code: 1

    Standard output:

    Standard error:
    /tmp/austral_69513e.c:94:14: warning: declaration of built-in function 'fprintf' requires inclusion of the header <stdio.h> [-Wbuiltin-requires-header]
      extern int fprintf(void* stream, const char* format, ...);
                 ^
    /tmp/austral_69513e.c:108:14: warning: declaration of built-in function 'fprintf' requires inclusion of the header <stdio.h> [-Wbuiltin-requires-header]
      extern int fprintf(void* stream, const char* format, ...);
                 ^
    /tmp/austral_69513e.c:162:16: warning: incompatible redeclaration of library function 'memmove' [-Wincompatible-library-redeclaration]
      extern void* memmove(void* destination, void* source, size_t count);
                   ^
    /tmp/austral_69513e.c:162:16: note: 'memmove' is a builtin with type 'void *(void *, const void *, unsigned long)'
    /tmp/austral_69513e.c:168:16: warning: incompatible redeclaration of library function 'memcpy' [-Wincompatible-library-redeclaration]
      extern void* memcpy(void* destination, void* source, size_t count);
                   ^
    /tmp/austral_69513e.c:168:16: note: 'memcpy' is a builtin with type 'void *(void *, const void *, unsigned long)'
    /tmp/austral_69513e.c:221:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
    }
    ^
    /tmp/austral_69513e.c:3294:10: warning: expression result unused [-Wunused-value]
            ((au_unit_t)(au_printf("true")));
             ^          ~~~~~~~~~~~~~~~~~~~
    /tmp/austral_69513e.c:3296:10: warning: expression result unused [-Wunused-value]
            ((au_unit_t)(au_printf("false")));
             ^          ~~~~~~~~~~~~~~~~~~~~
    /tmp/austral_69513e.c:3328:18: warning: expression result unused [-Wunused-value]
                    ((au_unit_t)(au_printf("%c", *((au_nat8_t*) au_array_index(array_tmp_ref0, i, sizeof(au_nat8_t))))));
                     ^          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    8 warnings generated.
    ld: error: undefined symbol: stdout
    >>> referenced by austral_69513e.c
    >>>               /tmp/austral_69513e-5b9a8f.o:(au_stdout)

    ld: error: undefined symbol: stdin
    >>> referenced by austral_69513e.c
    >>>               /tmp/austral_69513e-5b9a8f.o:(au_stdin)
    cc: error: linker command failed with exit code 1 (use -v to see invocation)
  Code:
    [no span available]

Thanks!

However, I expect this will only work until the next time the OpenBSD devs change the internals. I'm curious, why not write normal portable C code, with #include <stdio.h> etc? What I see in prelude.c seems to be just asking for trouble. If you like, I can try to draft a patch that does that.

This is to do with the compilation model. Since everything gets concatenated into one file, an FFI declaration for something in the header file will fail. It's not great, but it lets me ship the compiler as a single binary, which doesn't have to e.g. write the prelude files to an XDG data directory and compile them ahead of time.

This is to do with the compilation model. Since everything gets concatenated into one file, an FFI declaration for something in the header file will fail. It's not great, but it lets me ship the compiler as a single binary, which doesn't have to e.g. write the prelude files to an XDG data directory and compile them ahead of time.

Thanks for the explanation, but I can't figure out why standard #includes are incompatible with austral's method of catenating everything into one source file.
For the sake of argument I made this commit which removes the externs and uses #includes instead: https://github.com/austral/austral/commit/ece757f38ffc57aab5751a84a5426ad320689c5d
The hello-world program still compiles and works for me. Is there a simple example of something that would be broken by a change like https://github.com/austral/austral/commit/ece757f38ffc57aab5751a84a5426ad320689c5d?


Alternative Viewer

See if there is a better alternative to our current viewer to boost performance. Some work better than others, one example:
https://antimatter15.com/splat/

Here's a list with a loooot of viewers:
https://github.com/MrNeRF/awesome-3D-gaussian-splatting?tab=readme-ov-file#viewers

Alternative Viewers
Antimatter15 (https://github.com/antimatter15/splat)
Viewer tested the scene with around 120.000 splats

Can maintain constantly around 60fps
Fast movement doesn´t reduce fps

Con:

Overall quality is reduced minimally (probably to maintain good performance)

See pictures:

WebGL Vercel (https://webgl-gaussian-splatting.vercel.app)
Viewer tested the scene with around 120.000 splats

Can select preview resolution to reduce fps drop during movement
Acceptable performance during movement of the camera when preview resolution is set low
Good picture quality when camera stationary

Con:

When preview resolution ist set low and fast movement of the camera occures, the scene looks blurry
When preview resolution is set higher scene starts lagging during movement

See pictures:

WebGPU 1 (https://github.com/cvlab-epfl/gaussian-splatting-web)
Viewer tested the scene with 120.000 splats

Very poor performance ( 1-4 fps)
Output picture is square

WebGPU 3 (https://github.com/KeKsBoTer/web-splat)
Viewer tested the scene with around 5.000.000 splats (demo)

Somewhat laggy performance tho very high number of splats
Some splats were flickering making the scene look badish

Three.js (https://github.com/mkkellogg/GaussianSplats3D)
Viewer tested locally the scene with 120.000 splats

Good performance even during camera movement

Con:

Sometimes scene lagged for longer time (about 0.5 - 1 seconds)

A-Frame (https://github.com/quadjr/aframe-gaussian-splatting)
Demo tested
(code is derived from the WebGL implementation developed by antimatter15)

could maintain constant 60fps during fast movement

Conclusion
Since it would take too much time to implement antimatter15 in react-three-fiber, and no other reviewed viewer in react-three-fiber meets our needs, we've decided to optimize the viewer we're already using in the project.


[bug][framework] transaction effects returned by test_scenario do not include all created objects

The transaction effects returned by test_scenario::next_tx do not include all created objects when they are added to an ObjectBag. This behaviour is inconsistent with the effects reported in the same contract call using the sui client.
Steps to Reproduce Issue
Run tests for the following example move code:
module bag_test::bag_test {
    use sui::object::{Self, UID};
    use sui::transfer;
    use sui::tx_context::TxContext;
    use sui::object_bag::{ObjectBag, Self};

    struct Item has key, store {
        id: UID,
    }

    struct Container has key {
        id: UID,
        items: ObjectBag,
    }

    public entry fun create_container(ctx: &mut TxContext) {
        let id = object::new(ctx);
        let items = object_bag::new(ctx);
        transfer::share_object(Container {
            id,
            items,
        })
    }

    public entry fun create_item(
        container: &mut Container, ctx: &mut TxContext
    ) {
        let id = object::new(ctx);
        let item_id = object::uid_to_inner(&id);
        object_bag::add(
            &mut container.items,
            item_id,
            Item {
                id,
            }
        );
    }

    #[test]
    fun test_bag_example() {
        use sui::test_scenario;
        use std::vector;
        let client_address = @0xc0ffee;
        let scenario_val = test_scenario::begin(client_address);
        let scenario = &mut scenario_val;
        create_container(test_scenario::ctx(scenario));
        test_scenario::next_tx(scenario, client_address);
        let container = test_scenario::take_shared<Container>(scenario);
        create_item(&mut container, test_scenario::ctx(scenario));
        test_scenario::return_shared(container);
        let tx_effects = test_scenario::next_tx(scenario, client_address);
        let created = test_scenario::created(&tx_effects);

        // The `created` vector should have at least one element, namely the id of the created item
        assert!(vector::length(&created) >= 1, 0);

        test_scenario::end(scenario_val);
    }
}

Expected Result
The test should succeed. If the same code is deployed on a local sui testnet, calling create_item using the sui client, the effects will include the item in the created objects:
----- Transaction Effects ----
Status : Success
Created Objects:
  - ID: 0x487ed14d760bb0ed92d6d5e8eb723a390d92be5455abd87b2026d6e29dbc340a , Owner: Object ID: ( 0x68dca8e9b605efe457bf7af8e695be171b79eea2b18178f8744ab390a63d9d66 )
  - ID: 0x92b34b01c18beec96da077ceb766684eac46f77f80f32fb230e0bd38f81b6efb , Owner: Object ID: ( 0x487ed14d760bb0ed92d6d5e8eb723a390d9
2be5455abd87b2026d6e29dbc340a )

where
$ sui client object 0x92b34b01c18beec96da077ceb766684eac46f77f80f32fb230e0bd38f81b6efb
----- 0xd22cf812d9ed24a70054c91ce84dfec6303341a60150d21aeae0a13ea83d6870::bag_test::Item (0x92b34b01c18beec96da077ceb766684eac46f77f80f32fb230e0bd38f81b6efb[0x9]) -----
Owner: Object ID: ( 0x487ed14d760bb0ed92d6d5e8eb723a390d92be5455abd87b2026d6e29dbc340a )
Version: 0x9
Storage Rebate: 1284400
Previous Transaction: TransactionDigest(3qUhnyCBVyLpH3amG2BYGPujnbao8X8ghNnnRDjo8WFv)
----- Data -----
type: 0xd22cf812d9ed24a70054c91ce84dfec6303341a60150d21aeae0a13ea83d6870::bag_test::Item
id: 0x92b34b01c18beec96da077ceb766684eac46f77f80f32fb230e0bd38f81b6efb

Actual Result
The test fails. The transaction effects returned by test_scenario include no created objects.
System Information

OS: macOS Ventura 13.4
Compiler: cargo 1.69.0
sui version: Tested with sui at version https://github.com/MystenLabs/sui/commit/9588990ecf2b1c359b1cd2f2afbc3dce8ac110ba and https://github.com/MystenLabs/sui/commit/8b681515c0cf435df2a54198a28ab4ef574d202b

Hey @karlwuest thanks for the detailed steps to reproduce!
TL;DR: After digging in, this looks like a limitation in test_scenario, and I'm not sure there's a fix or improvement we can to test_scenario. But I will raise with some folks who know more and then revert here. My suggested workaround is to test for >= 1 items in the container by:

Getting the ID of the container in the test (e.g., you can get that from the shared effects at the end of the test).

Retrieving the object by ID from the store and testing length on that.

I.e., instead of checking state that depends on the fidelity of reported effects by test_scenario, instead check state based on stored / mutated objects.

Long version, according to my best understanding after going through the code:

The transaction effects reported by test_scenario::next_tx aren't accumulated. Each invocation of next_tx returns the results / transaction effects of the previous transaction.

This means the created effects for create_container are not observable toward the end of test (after calling next_tx again), but you will see them in the results of next_tx called earlier in the test.

Transaction effects for test_scenario are committed / recorded on sui::transfer calls.

This means transaction effects are observable for next_tx after calling create_container because of transfer::share_object. You can see a create effect on next_tx for this call in the debug output below part 1.
This also means transaction effects are observable for next_tx after calling return_shared, which indirectly calls transfer::share_object_impl (see part 3 output below)
Because of this, there is no observable create effect when calling create_item (limitation here: there is no recording of this in test_scenario, and no function (e.g., like transfer is invoked to expose this info for us to record. effectively, there is no transaction). See part 2 output below.
Once return_shared is called, we do see that container is mutated, and that fact is recorded in written effects, but no effects are created (working-as-intended, because per bullet above, test_scenario doesn't know about this newly created item). See part 3.

From here it makes sense that we can see observable effects when calling functions on a local testnet (effects are accumulated and committed / recorded for the transaction involving child object, which test_scenario doesn't see in the window where create_item is called in the test).

So I'm not sure there's a way to improve this based on how test_scenario works, but will forward for input from rest of the folks!
Code:
    #[test]
    fun test_bag_example() {
        use sui::test_scenario;
        use std::vector;
        let client_address = @0xc0ffee;
        let scenario_val = test_scenario::begin(client_address);
        let scenario = &mut scenario_val;
        create_container(test_scenario::ctx(scenario));
        let tx_effects = test_scenario::next_tx(scenario, client_address);

        sui::test_utils::print(b"after create_container");
        std::debug::print(&tx_effects);

        let container = test_scenario::take_shared<Container>(scenario);
        create_item(&mut container, test_scenario::ctx(scenario));

        let tx_effects = test_scenario::next_tx(scenario, client_address);
        sui::test_utils::print(b"after create_item");
        std::debug::print(&tx_effects);
        // std::debug::print(&container);  // uncomment to see that item is added

        test_scenario::return_shared(container);

        let tx_effects = test_scenario::next_tx(scenario, client_address);
        sui::test_utils::print(b"after return_shared");
        std::debug::print(&tx_effects);
        let created = test_scenario::created(&tx_effects);

        // The `created` vector should have at least one element, namely the id of the created item
        assert!(vector::length(&created) >= 1, 0);

        test_scenario::end(scenario_val);
    }

Debug log, separated for readability
part 1 created effect for container
[debug] "after create_container"
[debug] 0x2::test_scenario::TransactionEffects {
  created: [
    0x2::object::ID {
      bytes: @0x34401905bebdf8c04f3cd5f04f442a39372c8dc321c29edfb4f9cb30b23ab96
    }
  ],
  written: [],
  deleted: [
    0x2::object::ID {
      bytes: @0xa4137e2ed945e7f4e8c307001c32e97472fb3eebb8f7b4ab7534b447d22da89b
    }
  ],
  transferred_to_account: 0x2::vec_map::VecMap<0x2::object::ID, address> {
    contents: []
  },
  transferred_to_object: 0x2::vec_map::VecMap<0x2::object::ID, 0x2::object::ID> {
    contents: []
  },
  shared: [
    0x2::object::ID {
      bytes: @0x34401905bebdf8c04f3cd5f04f442a39372c8dc321c29edfb4f9cb30b23ab96
    }
  ],
  frozen: [],
  num_user_events: 0
}

part 2 no observable effects in test_scenario for create_item
[debug] "after create_item"
[debug] 0x2::test_scenario::TransactionEffects {
  created: [],
  written: [],
  deleted: [],
  transferred_to_account: 0x2::vec_map::VecMap<0x2::object::ID, address> {
    contents: []
  },
  transferred_to_object: 0x2::vec_map::VecMap<0x2::object::ID, 0x2::object::ID> {
    contents: []
  },
  shared: [],
  frozen: [],
  num_user_events: 0
}

part 3 next_tx returns effects (sees mutated / written container).
[debug] "after return_shared"
[debug] 0x2::test_scenario::TransactionEffects {
  created: [],
  written: [
    0x2::object::ID {
      bytes: @0x34401905bebdf8c04f3cd5f04f442a39372c8dc321c29edfb4f9cb30b23ab96
    }
  ],
  deleted: [
    0x2::object::ID {
      bytes: @0xa4137e2ed945e7f4e8c307001c32e97472fb3eebb8f7b4ab7534b447d22da89b
    }
  ],
  transferred_to_account: 0x2::vec_map::VecMap<0x2::object::ID, address> {
    contents: []
  },
  transferred_to_object: 0x2::vec_map::VecMap<0x2::object::ID, 0x2::object::ID> {
    contents: []
  },
  shared: [
    0x2::object::ID {
      bytes: @0x34401905bebdf8c04f3cd5f04f442a39372c8dc321c29edfb4f9cb30b23ab96
    }
  ],
  frozen: [],
  num_user_events: 0
}

Thanks for looking into this!
The assert!(vector::length(&created) >= 1, 0) is just in this example to show the bug. My original goal was to retrieve the ID of the created object (which is needed for future function calls). The workaround that we've been using is to have the create_item function return the item_id of the object. This works for us, but, of course, I still wanted to report the bug.

@rvantonder @karlwuest is this issue still relevant?

Don't remember the exact details (one sign this is too old to keep open) and since it's not easily fixable (second sign) and since there's a plausible workaround, I think we can close this


How to apply the boundary loss to 3D images both efficiently and correctly?

Hi, thanks for sharing your code. I am trying to use the boundary loss for 3D (really high-resolution) image segmentation, but I have problems with the implementation of the loss function both efficiently and correctly. For 3D image segmentation, a popular way is to train the networks using image patches. Often the time, the training samples include image patches that belong to the background. And for these samples, a naive generalization of your implementation may give SDM that are all 0s (using eras version of the loss function). To me, this does not make sense because even if these samples do not contain any foreground voxels, the SDM should not be 0s in reality. I think it makes more sense if the SDM is calculated based on the entire images rather than image patches. How do you think about this problem?
Also, I found it pretty time consuming to calculate SDM in 3D cases. How can the time efficiency be improved?
Thanks

The solution is to pre-compute offline the distance map in 3D, save them into a .npy in the with the axises kxyz, with k being the class axis. Pay attention to spatial resolution at this step -- the scipy function has an extra, optional parameter for that.
Then, in the dataloader, you load the 3d distmap as is (no extra transform besides converting to a tensor), and subpatch it as the same time as the original image.
You can then do the usual multiplication between distance map and softmaxes.
This is what I implemented for the extension, but didn't had time to put it in the repo yet. I will do so soon, and then point to the exact code parts doing that, but this should already give you a rough idea on how to proceed. Let me know if you need other details in the meantime.
Hoel

The solution is to pre-compute offline the distance map in 3D, save them into a .npy in the with the axises kxyz, with k being the class axis. Pay attention to spatial resolution at this step -- the scipy function has an extra, optional parameter for that.
Then, in the dataloader, you load the 3d distmap as is (no extra transform besides converting to a tensor), and subpatch it as the same time as the original image.
You can then do the usual multiplication between distance map and softmaxes.
This is what I implemented for the extension, but didn't had time to put it in the repo yet. I will do so soon, and then point to the exact code parts doing that, but this should already give you a rough idea on how to proceed. Let me know if you need other details in the meantime.
Hoel

Yes, this is a solution that can solve part of the problem because for training data that are obtained via data augmentation, it seems there is no better choice other than computing the SDM on the fly. In this case, training the network efficiently can be a big issue.
BTW, I want to know if the segmentation performance is sensitive to the value of loss weight for boundary loss?
Thanks

With respect to the data augmentation

there is no better choice other than computing the SDM on the fly

When you refer to "on the fly", you mean to compute the distance map inside the loss function ?
The way I see it, the pre-computed distance map can be augmented as well, just like we perform the augmentation on the original ground truth. The overall code would look like this:
from pathlib import Path
from Typing import Dict, List, Tuple

from torch import Tensor
from torch.utils.data import Dataset

class DistDataset(Dataset):
        def __init__(self, *args, **kwargs):
                ...
                self.files: List[Tuple[Path, Path, Path]]

        def __getitem__(index: int) -> Dict[str, Tensor]:
                img_path, gt_path, dist_path = self.files[index]

                # ... perform the transforms here

                aug_img, aug_gt, aug_dist = augment(img, gt, dist)
                del img, gt, dist  # Avoid returning those by accident

                return {"img": aug_img,  # CWH shape
                        "gt": aug_gt, # KWH shape
                        "distmap": aug_dist}  # KWH shape

# Then in the training loop
α = 0.01
for data in train_loader:
        imgs = data["img"].to(device)  # BKWH shape
        gts = data["gt"].to(device)  # BKWH shape
        dists = data["distmap"].to(device)  # BKWH shape

        optimizer.zero_grads()

        pred_probs = softmax(net(imgs))

        dsc_loss = DiceLoss(gts, pred_probs)
        bl_loss = BoundaryLoss(dists, pred_probs)

        total_loss = dsc_loss + α * bl_loss
        total_loss.backward()
        optimizer.step()

BTW, I want to know if the segmentation performance is sensitive to the value of loss weight for boundary loss?

In our experiments, it was somewhat sensitive, but still consistently gave some improvement even with a sub-optimal value: Table 3 in our extension:

Increasing and rebalancing the values were not only better in perf, but also much simpler to tune -- to me that is their main advantage.

Thanks for your response. I tried your loss function on our dataset, however, I have not seen improved performance till now. I want to know if the simplification from the differential form to integral form hold for 3D cases as the 2D example you show in your paper? The reason I ask this question is that I think maybe the simplification does not hold for 3D boundary and 3D surface. If it still hold, could you please clarify and send me some reference articles to show that. Thanks!
Get Outlook for iOShttps://aka.ms/o0ukef

From: Hoel KERVADEC<EMAIL_ADDRESS>Sent: Sunday, November 29, 2020 12:40:21 PM
To: LIVIAETS/boundary-loss<EMAIL_ADDRESS>Cc: Chen, Xiaoyang<EMAIL_ADDRESS>Author<EMAIL_ADDRESS>Subject: Re: [LIVIAETS/boundary-loss] How to apply the boundary loss to 3D images both efficiently and correctly? (#29)
With respect to the data augmentation
there is no better choice other than computing the SDM on the fly
When you refer to "on the fly", you mean to compute the distance map inside the loss function ?
The way I see it, the pre-computed distance map can be augmented as well, just like we perform the augmentation on the original ground truth. The overall code would look like this:
from pathlib import Path
from Typing import Dict, List, Tuple
from torch import Tensor
from torch.utils.data import Dataset
class DistDataset(Dataset):
    def __init__(self, *args, **kwargs):

            ...

            self.files: List[Tuple[Path, Path, Path]]

    def __getitem__(index: int) -> Dict[str, Tensor]:

            img_path, gt_path, dist_path = self.files[index]

            # ... perform the transforms here

            aug_img, aug_gt, aug_dist = augment(img, gt, dist)

            del img, gt, dist  # Avoid returning those by accident

            return {"img": aug_img,  # CWH shape

                    "gt": aug_gt, # KWH shape

                    "distmap": aug_dist}  # KWH shape

Then in the training loop
α = 0.01
for data in train_loader:
    imgs = data["img"].to(device)  # BKWH shape

    gts = data["gt"].to(device)  # BKWH shape

    dists = data["distmap"].to(device)  # BKWH shape

    optimizer.zero_grads()

    pred_probs = softmax(net(imgs))

    dsc_loss = DiceLoss(gts, pred_probs)

    bl_loss = BoundaryLoss(dists, pred_probs)

    total_loss = dsc_loss + α * bl_loss

    total_loss.backward()

    optimizer.step()

BTW, I want to know if the segmentation performance is sensitive to the value of loss weight for boundary loss?
In our experiments, it was somewhat sensitive, but still consistently gave some improvement even with a sub-optimal value: Table 3 in our extensionhttps://arxiv.org/pdf/1812.07032.pdf#page=17:
[Screenshot_2020-11-29 Boundary loss for highly unbalanced segmentation - 1812 07032 pdf]https://user-images.githubusercontent.com/4191866/100549218-aa836b80-323f-11eb-80ce-8a4eaed1b952.png
Increasing and rebalancing the values were not only better in perf, but also much simpler to tune -- to me that is their main advantage.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHubhttps://github.com/LIVIAETS/boundary-loss/issues/29#issuecomment-735429571, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AHVAPZ5B43LIUQADNU6VNPTSSKBQLANCNFSM4UFGJVQQ.

Also, what does ‘rebalance’ mean and how to implement it? Thanks
Get Outlook for iOShttps://aka.ms/o0ukef

From: Chen, Xiaoyang<EMAIL_ADDRESS>Sent: Sunday, November 29, 2020 2:28:53 PM
To: LIVIAETS/boundary-loss<EMAIL_ADDRESS>LIVIAETS/boundary-loss<EMAIL_ADDRESS>Cc: Author<EMAIL_ADDRESS>Subject: Re: [LIVIAETS/boundary-loss] How to apply the boundary loss to 3D images both efficiently and correctly? (#29)
Thanks for your response. I tried your loss function on our dataset, however, I have not seen improved performance till now. I want to know if the simplification from the differential form to integral form hold for 3D cases as the 2D example you show in your paper? The reason I ask this question is that I think maybe the simplification does not hold for 3D boundary and 3D surface. If it still hold, could you please clarify and send me some reference articles to show that. Thanks!
Get Outlook for iOShttps://aka.ms/o0ukef

From: Hoel KERVADEC<EMAIL_ADDRESS>Sent: Sunday, November 29, 2020 12:40:21 PM
To: LIVIAETS/boundary-loss<EMAIL_ADDRESS>Cc: Chen, Xiaoyang<EMAIL_ADDRESS>Author<EMAIL_ADDRESS>Subject: Re: [LIVIAETS/boundary-loss] How to apply the boundary loss to 3D images both efficiently and correctly? (#29)
With respect to the data augmentation
there is no better choice other than computing the SDM on the fly
When you refer to "on the fly", you mean to compute the distance map inside the loss function ?
The way I see it, the pre-computed distance map can be augmented as well, just like we perform the augmentation on the original ground truth. The overall code would look like this:
from pathlib import Path
from Typing import Dict, List, Tuple
from torch import Tensor
from torch.utils.data import Dataset
class DistDataset(Dataset):
    def __init__(self, *args, **kwargs):

            ...

            self.files: List[Tuple[Path, Path, Path]]

    def __getitem__(index: int) -> Dict[str, Tensor]:

            img_path, gt_path, dist_path = self.files[index]

            # ... perform the transforms here

            aug_img, aug_gt, aug_dist = augment(img, gt, dist)

            del img, gt, dist  # Avoid returning those by accident

            return {"img": aug_img,  # CWH shape

                    "gt": aug_gt, # KWH shape

                    "distmap": aug_dist}  # KWH shape

Then in the training loop
α = 0.01
for data in train_loader:
    imgs = data["img"].to(device)  # BKWH shape

    gts = data["gt"].to(device)  # BKWH shape

    dists = data["distmap"].to(device)  # BKWH shape

    optimizer.zero_grads()

    pred_probs = softmax(net(imgs))

    dsc_loss = DiceLoss(gts, pred_probs)

    bl_loss = BoundaryLoss(dists, pred_probs)

    total_loss = dsc_loss + α * bl_loss

    total_loss.backward()

    optimizer.step()

BTW, I want to know if the segmentation performance is sensitive to the value of loss weight for boundary loss?
In our experiments, it was somewhat sensitive, but still consistently gave some improvement even with a sub-optimal value: Table 3 in our extensionhttps://arxiv.org/pdf/1812.07032.pdf#page=17:
[Screenshot_2020-11-29 Boundary loss for highly unbalanced segmentation - 1812 07032 pdf]https://user-images.githubusercontent.com/4191866/100549218-aa836b80-323f-11eb-80ce-8a4eaed1b952.png
Increasing and rebalancing the values were not only better in perf, but also much simpler to tune -- to me that is their main advantage.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHubhttps://github.com/LIVIAETS/boundary-loss/issues/29#issuecomment-735429571, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AHVAPZ5B43LIUQADNU6VNPTSSKBQLANCNFSM4UFGJVQQ.

Thanks for your response. I tried your loss function on our dataset, however, I have not seen improved performance till now. I want to know if the simplification from the differential form to integral form hold for 3D cases as the 2D example you show in your paper? The reason I ask this question is that I think maybe the simplification does not hold for 3D boundary and 3D surface. If it still hold, could you please clarify and send me some reference articles to show that. Thanks!

Yes the result still holds, though in 3D you need to take into account the spatial resolution of each axis, as it might differ. The updated distance computation function now looks like this:
def one_hot2dist(seg: np.ndarray, resolution: Tuple[float, float, float] = None,
                 dtype=None) -> np.ndarray:
    assert one_hot(torch.tensor(seg), axis=0)
    K: int = len(seg)

    res = np.zeros_like(seg, dtype=dtype)
    for k in range(K):
        posmask = seg[k].astype(np.bool)

        if posmask.any():
            negmask = ~posmask
            res[k] = eucl_distance(negmask, sampling=resolution) * negmask \
                - (eucl_distance(posmask, sampling=resolution) - 1) * posmask
        # The idea is to leave blank the negative classes
        # since this is one-hot encoded, another class will supervise that pixel

    return res

resolution = None correspond to sampling = (1, 1, 1)
Another thing to take into account: if the space between each slice becomes too big (like 1cm on the z axis while it is 1mm on the x and y axises), then maybe the 3D distance will not make much sense. It will depend on your application.

Also, what does ‘rebalance’ mean and how to implement it? Thanks

Rebalancing correspond to start with a high weight for the DSC loss weight, and a smaller one on the boundary loss, and to slowly shift them:
α = 0.01

for e in range(epochs):
        for data in train_loader:
                ...

                total_loss = (1 - α) * dsc_loss + α * bl_loss
                total_loss.backward()
                optimizer.step()

        α = max(α + 0.01, 0.99)

I tried to understand the the mathematics in your paper. It is interesting to see the beautiful connection between Eq 2 and 3. However, I found it difficult to understand your derivation to connect the two. Specifically, in the paper, you mentioned that the two can be connected using the following:

To me, it is not obvious why the first two are equivalent because getting dD_G/dq is not a constant for the second term after the minus sign in
 is also related to q and I think cannot be easily formulated.
Could you please explain more on this?

That one fell through the cracks (sorry for that), please feel free to re-open/reply if still relevant.