Skip to content

Test3devmerge - #278

Merged
hiroshisuga merged 45 commits into
test3laserPRfrom
test3devmerge
Aug 9, 2026
Merged

Test3devmerge#278
hiroshisuga merged 45 commits into
test3laserPRfrom
test3devmerge

Conversation

@hiroshisuga

Copy link
Copy Markdown
Owner

What does this PR do?

Closes Issue(s)

Closes #

Motivation

How to test

More

  • Added/updated documentation

GuiLeme and others added 30 commits June 26, 2026 14:51
Run document upload handling asynchronously after meeting creation for improved API response time.
Replaces grails-async task {} with a dedicated fixed-size
executor owned by PresentationService. grails-async's default factory
is an unbounded thread pool with no supervision, and exceptions raised
inside the task closure are silently swallowed instead of surfacing
anywhere. submitPresentationTask() logs any escaping failure with
meeting/source context and caps concurrency via the existing
numConversionThreads-style property pattern (numPresentationDownloadThreads,
default 5), removing the grails-async dependency entirely.

Also drops the now-unreachable invalid() call inside
downloadAndProcessDocument's UnsupportedEncodingException handler,
since that method runs off the request thread and can no longer render
a response.

Updates docs for the async create/insertDocument semantics and the new
numPresentationDownloadThreads property.
…async tasks

Review follow-up: filename derivation/validation moves out of
downloadAndProcessDocument into resolvePresentationFilename(), which runs
on the request thread before submitPresentationTask at all three submit
sites (default presentation, URL documents, raw-bytes documents). Invalid
filenames are rejected synchronously with an error log and no task is
spawned.

This also closes two gaps: URLDecoder.decode's IllegalArgumentException
(malformed percent-encoding) is now caught — unlike
UnsupportedEncodingException it is actually reachable — and the raw-bytes
path, whose internal name validation result was silently discarded (pres
stays null so processUploadedFile never runs and the failure never reaches
the meeting), now rejects invalid names before a task exists at all.
- Replace Executors.newFixedThreadPool (unbounded queue) with a
  ThreadPoolExecutor backed by a bounded queue (threads x 20) and an
  AbortPolicy. submitPresentationTask now catches RejectedExecutionException,
  logs it with meeting/source context and returns false, so a burst of
  create/insertDocument calls can no longer grow the queue until the heap is
  exhausted.
- uploadDocuments defers task submission until every filename is validated.
  insertDocument now returns a FAILED response when a document is rejected for
  an invalid filename instead of reporting SUCCESS for a skipped document.
  create still skips invalid documents and creates the meeting with the valid
  ones.
- resolvePresentationFilename derives the name from the URL path only, dropping
  any query string or fragment (e.g. presigned S3 links) before decoding,
  mirroring Util.extractFilenameFromUrl. The download still uses the full URL.
- docs: describe the bounded queue/rejection behavior and drop the shell prompt
  marker (MD014).
The create handler now calls uploadDocuments before respondWithConference,
so an unexpected exception in the synchronous upload-handling path would
skip the response and return a 500 for a meeting that was actually created.
Wrap that call in try/catch: log the failure and still respond with success,
consistent with async download/processing failures being non-fatal to the
API response.

Clamp the download pool size to at least 1. numDownloadThreads is injected
as a String, so a configured "0" is truthy and slips past the Elvis default;
0 or a negative value makes the ThreadPoolExecutor constructor throw and
fails bean initialization at startup.

Document that a presentation task rejected because the pool is saturated is
not uploaded and is not reflected in the create/insertDocument response,
only logged.
refactor(bbb-web): process pre-uploaded slides async on a bounded pool
…gbluebutton#25439)

* Translate en.json in it_IT

100% translated source file: 'en.json'
on 'it_IT'.

* Translate en.json in zh_TW

100% translated source file: 'en.json'
on 'zh_TW'.

* Translate en.json in ja

100% translated source file: 'en.json'
on 'ja'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
…npm_and_yarn/docs/postcss-8.5.23

build(deps): bump postcss from 8.5.15 to 8.5.23 in /docs
…25522)

Bumps [body-parser](https://github.com/expressjs/body-parser) from 2.2.1 to 2.3.0.
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](expressjs/body-parser@v2.2.1...v2.3.0)

---
updated-dependencies:
- dependency-name: body-parser
  dependency-version: 2.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…on#25520)

Bumps [shell-quote](https://github.com/ljharb/shell-quote) from 1.8.4 to 1.10.0.
- [Changelog](https://github.com/ljharb/shell-quote/blob/main/CHANGELOG.md)
- [Commits](ljharb/shell-quote@v1.8.4...v1.10.0)

---
updated-dependencies:
- dependency-name: shell-quote
  dependency-version: 1.10.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…bigbluebutton#25514)

Move getJoinUrl out of the integration API listing into a new
"Internal API calls" section, and document the other session-token
authenticated, client-only endpoints alongside it: stuns, signOut and
learningDashboard.

These endpoints are authenticated with a per-user sessionToken issued by
/join rather than a shared-secret checksum, and are only reachable by the
BigBlueButton HTML5 client -- not by integrations (Greenlight, Moodle) or
load balancers (Scalelite, b3scale), which never see the session token.
The new section makes that boundary explicit and warns integrators not to
build on these endpoints.

All four endpoints are routed for both GET and POST (per UrlMappings and
confirmed against a running server), so getJoinUrl is labelled accordingly.

Addresses bigbluebutton#24212.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AudioFloorManager's FloorState.talkingStateChanges has no actual usage.
Drop the field and the consequently stale cleanupOldState.
AudioFloorManager is an akka-apps-wide singleton, which may cause
collisions when handling audio floor events.

Turn AudioFloorManager into a per-meeting class held by LiveMeeting, so
floor grants, releases, CDs and pending queues are meeting-scoped and
releases always resolve in the holder's own meeting, and tear it down
from a MeetingActor postStop hook, which covers every termination path.
There are a few issues regarding floor grant scheduling vs cooldown
handling:
- Each pending floor grant runs off its own timer on a manually managed
scheduler thread. A grant that fires inside the cooldown period
is rejected and never re-scheduled, and new scheduling is blocked
if the user keeps talking - so two users starting to talk within the
cooldown of each other leave the second one starved of the floor until
they stop and restart talking.
- Timers that are not the head of the grant queue are no-ops, which
leaves orphaned queue entries that can block actual floor grants tha
come in later.
- The timer task mutates VoiceUsers and emits floor events decoupled
from the meeting actor's lifecycle - which races meeting events and is
just weird

Replace the per-queued grant timers with a single re-scheduled grant
dispatch that always evaluates the queue head at the earliest instant a
grant can succeed (talking deadline or cooldown expiry, whichever is
later) and re-runs on every queue or floor-state change.

This includes the rewrite of the scheduler to use Pekko's scheduleOnce
via an internal DispatchFloorGrantsInternalMsg to the meeting actor,
handled in like the other internal meeting timers, so all floor state is
inside the meeting actor lifecycle.
When a floor holder leaves, the release itself starts a cooldown that
defers the grant to the next pending speaker until after the cooldown
elapses. The cooldown exists to space out floor switches only - a release
event always should come after the cooldown already acted.

Enforce cooldowns on grants only, so a pending speaker is promoted as soon
as their talking deadline allows.
speakingStartTimes entries are removed only by explicit stop-talking or
left-voice events. A user whose events are lost (disconnect, ...) leaves an
entry behind until meeting end. Two obvious issues: queue buildup and
floor grant block for the affected user.

Prune speaking state entries older than five minutes, dropping matching
pending grants with them. TTL may be tweaked later based on observation.
…defaults

Align fallback config values for voiceConf.floorControl and
minTalkingDuration with the default application.conf values.
The grant dispatch dequeues the pending item before granting it, so a
grant attempt that fails to execute drops the speaker from the queue
and the re-scheduled dispatch retries the next queued speaker instead.

Dequeue only after the grant went through; a half-granted holder is still
dequeued by the dispatch's stale cleanup routine on retry.
…oors-fixes

Backport: "fix(audio): assorted fixes and improvements to LiveKit's floor manager"
ramonlsouza and others added 15 commits July 29, 2026 11:29
…hat messages hook (it remains static throughout the meeting) (bigbluebutton#25539)
fix: MeetingActor analytics discards VoiceUserState.callerName, logs ERROR after user leaves
Especially under reconnects, BBB <-> LiveKit state can drift apart.
This is both due to them being two separate systems, but also due to
the fact that akka-apps itself makes VoiceUsers (which is the basic
media participant unit in BBB) just _very loosely coupled_ to the
Users2x model of users. This may cause a few issues, such as a client
being marked as out of audio after a reconnect with no way to recover
it - even though it got back its media session.

Introduce a voice user reconciler that centralizes VoiceUsers <->
Users2x state reconciliation and makes it easier to reason about the
state of a voice user in BBB and propagate it to LiveKit.

In addition to centralizing something that was spread across akka, this
also introduces a new concept of "fencing" a voice user: keeping it
alive, for a time, with a downgraded permission state when it is no
longer associated with a meeting user. Fencing makes the reconnection
process smoother (no VoiceUser teardown, just permission up/downgrade)
and more robust (permissions adhere to state being consistent across
Users2x and VoiceUsers).
Fencing, when applicable, is done at: the voice conf join (if
orphaned), and MeetingActor's periodic user audit.

For LiveKit, bbb-webrtc-sfu acts on media permission up/down grades as
well as voice user ejections. For mediasoup/FreeSWITCH, it acts on
ejections.
v2.24.0
---
* feat(livekit): handle participant permission updates from akka
* feat(livekit): ack participant permission and voice eject outcomes
…ed (bigbluebutton#25535)

Viewers joining a session that already had an external video shared got a silent
video. Audio only came back if they nudged the BBB volume slider or pressed the
reload button in the player toolbar.

When the browser blocks autoplay with sound, YouTube's embed does not surface the
failure: it mutes itself inside the iframe and plays anyway. The `muted` prop on
this side therefore stays false, and react-player only calls unmute() when that
prop *changes*, so nothing ever undoes the mute. Chrome gates unmuted autoplay on
user activation or the per-profile Media Engagement Index, which is why this is
invisible on an established profile and reproduces in incognito, on a fresh
profile, or for a first-time participant. Both known workarounds line up with the
mechanism exactly: changeVolume calls unMute directly, and the reload button
remounts the iframe close enough to a click to inherit its transient activation.

The existing autoplay warning cannot cover this. It triggers on
`reactPlayerPlaying !== playing`, and muted playback is still playback, so the
condition is never met and the client believes everything is fine. The 2.x
detector had the same blind spot by design: it fired only when the player became
ready without ever playing, which assumed a blocked autoplay meant no playback at
all. That is no longer the failure mode.

Reconcile the provider's real muted state against the UI's on the first play and
on subsequent progress ticks, and unmute when the two diverge:

- Read the muted flag from the provider rather than from component state, since
  detecting where the two disagree is the whole point. isMuted() for YouTube,
  getMuted() for Vimeo and Twitch, .muted for HTML5 media playback.
- Disarm without acting when the provider reports unmuted, or reports nothing at
  all, so a viewer who mutes through the provider's own controls is not
  overridden a tick later.
- Unmute immediately when the document already has user activation. That covers
  effectively every real join and avoids making the viewer click for their audio.
- Always also arm a one-shot pointerup/keydown listener that unmutes
  synchronously inside the handler. That is the only moment the browser is
  guaranteed to honour an unmute rather than answering it by pausing the media, so
  it is what actually guarantees recovery. Both event types are activation
  triggers, so keyboard-only viewers are covered too.
- One automatic attempt plus one gesture-anchored attempt means the recovery can
  never ping-pong with the viewer-side auto-resume in handleOnStop, so there is no
  retry budget to tune.
- Disarm before the await rather than after, so an onPlay and a progress tick in
  flight together cannot both clear the guard and run the recovery twice.
- Re-arm per player mount in handleOnStart, before its first await, since
  react-player invokes onStart then onPlay synchronously and the async tail would
  otherwise undo that attempt's result. Release the gesture listener when it
  fires, on unmount, and on remount.

Volume needs no extra plumbing: the player mounts unmuted, so react-player has
already applied the stored volume by the time the unmute lands.

Verified manually in an incognito window against a live server, which is the only
place the behaviour reproduces. Headless Chromium's autoplay policy does not
match a real profile, so an E2E test here would be either vacuous or flaky.
…x-lk-reconciliation

[3.0] refactor(audio): better BBB<->LiveKit state reconciliation on reconnects, bbb-webrtc-sfu@v2.24.0- bigbluebutton#25550
* docs: iteration doc sync for 3.0.33

Covers documentation-worthy changes on v3.0.x-release since the v3.0.32
tag that were not yet reflected in the docs:

- new-features.md: Panopto external video player; the new
  public.whiteboard.slideSwapDecodeTimeoutMs client setting; corrected the
  html5PluginSdkVersion line to 0.0.104; tagged
  maxSharedNotesInitialContentUrlPayloadSize with 3.0.33 and added
  numPresentationDownloadThreads to the bbb-web properties ledger.
- create.tsx: "(added 3.0.33)" on sharedNotesInitialContentMarkdown and
  sharedNotesInitialContentMarkdownUrl.
- api.md: the three shared-notes initial-content create parameters added to
  the "Updated in 3.0" list, tagged with the point release that shipped them.
- plugins.md: useTimer hook (plugin SDK 0.0.104) and the new senderRole
  field on useLoadedChatMessages.
- faq.md: external video line now mentions Panopto.
…on#25563)

Bumps [ip-address](https://github.com/beaugunderson/ip-address) from 10.2.0 to 10.4.0.
- [Release notes](https://github.com/beaugunderson/ip-address/releases)
- [Commits](beaugunderson/ip-address@v10.2.0...v10.4.0)

---
updated-dependencies:
- dependency-name: ip-address
  dependency-version: 10.4.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…n#25569)

Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.4 to 3.1.5.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](fastify/fast-uri@v3.1.4...v3.1.5)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…tton#25572)

Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.2 to 3.1.5.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](fastify/fast-uri@v3.1.2...v3.1.5)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…n#25556)

Bumps [sanitize-html](https://github.com/apostrophecms/apostrophe/tree/HEAD/packages/sanitize-html) from 2.17.4 to 2.17.5.
- [Changelog](https://github.com/apostrophecms/apostrophe/blob/main/packages/sanitize-html/CHANGELOG.md)
- [Commits](https://github.com/apostrophecms/apostrophe/commits/sanitize-html@2.17.5/packages/sanitize-html)

---
updated-dependencies:
- dependency-name: sanitize-html
  dependency-version: 2.17.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…bluebutton#25573)

Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.13 to 1.1.18.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](juliangruber/brace-expansion@v1.1.13...v1.1.18)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.18
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@hiroshisuga
hiroshisuga merged commit 9ad14d4 into test3laserPR Aug 9, 2026
319 of 367 checks passed
@hiroshisuga
hiroshisuga deleted the test3devmerge branch August 9, 2026 13:19
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

🚨 Automated tests failed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants