Audio changes (#5593)

* Squash tested commits

* remove the code jack is concerned about

* Apply suggestions from code review

* more log lines

* more log lines

* format

* formatting

* style(Rename Xms and Xmx mentions): Rename Xms and Xmx to more use friendly names

- Change Xms to "Initial Heapsize"
- Change Xmx to "Max Heapsize"

Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com>
This commit is contained in:
Draper
2022-03-28 16:23:30 +01:00
committed by GitHub
parent 5a5b22003f
commit 9ec85d4819
28 changed files with 1629 additions and 599 deletions

View File

@@ -1,21 +1,128 @@
import asyncio
import contextlib
import math
import platform
import re
import sys
import time
from enum import Enum, unique
from pathlib import Path
from typing import MutableMapping
from typing import MutableMapping, Tuple, Union
import discord
import psutil
from red_commons.logging import getLogger
from redbot.core import commands
from redbot.core.bot import Red
from redbot.core.i18n import Translator
log = getLogger("red.cogs.Audio.task.callback")
_ = Translator("Audio", Path(__file__))
def get_max_allocation_size(exec) -> Tuple[int, bool]:
if platform.architecture(exec)[0] == "64bit":
max_heap_allowed = psutil.virtual_memory().total
thinks_is_64_bit = True
else:
max_heap_allowed = 4 * 1024**3
thinks_is_64_bit = False
return max_heap_allowed, thinks_is_64_bit
def get_jar_ram_defaults() -> Tuple[str, str]:
min_ram = 64 * 1024**2
# We don't know the java executable at this stage - not worth the extra work required here
max_allocation, is_64bit = get_max_allocation_size(sys.executable)
max_ram_allowed = max_allocation * 0.5 if is_64bit else max_allocation
max_ram = max(min_ram, max_ram_allowed)
size_name = ("", "K", "M", "G", "T")
i = int(math.floor(math.log(min_ram, 1024)))
p = math.pow(1024, i)
s = int(min_ram // p)
min_ram = f"{s}{size_name[i]}"
i = int(math.floor(math.log(max_ram, 1024)))
p = math.pow(1024, i)
s = int(max_ram // p)
max_ram = f"{s}{size_name[i]}"
return min_ram, max_ram
MIN_JAVA_RAM, MAX_JAVA_RAM = get_jar_ram_defaults()
DEFAULT_LAVALINK_YAML = {
# The nesting structure of this dict is very important, it's a 1:1 mirror of application.yaml in JSON
"yaml__server__address": "localhost",
"yaml__server__port": 2333,
"yaml__lavalink__server__password": "youshallnotpass",
"yaml__lavalink__server__sources__http": True,
"yaml__lavalink__server__sources__bandcamp": True,
"yaml__lavalink__server__sources__local": True,
"yaml__lavalink__server__sources__soundcloud": True,
"yaml__lavalink__server__sources__youtube": True,
"yaml__lavalink__server__sources__twitch": True,
"yaml__lavalink__server__sources__vimeo": True,
"yaml__lavalink__server__bufferDurationMs": 400,
"yaml__lavalink__server__frameBufferDurationMs": 1000,
# 100 pages - 100 entries per page = 10,000 tracks which is the Audio Limit for a single playlist.
"yaml__lavalink__server__youtubePlaylistLoadLimit": 100,
"yaml__lavalink__server__playerUpdateInterval": 1,
"yaml__lavalink__server__youtubeSearchEnabled": True,
"yaml__lavalink__server__soundcloudSearchEnabled": True,
"yaml__lavalink__server__gc_warnings": True,
"yaml__metrics__prometheus__enabled": False,
"yaml__metrics__prometheus__endpoint": "/metrics",
"yaml__sentry__dsn": "",
"yaml__sentry__environment": "",
"yaml__logging__file__max_history": 15,
"yaml__logging__file__max_size": "10MB",
"yaml__logging__path": "./logs/",
"yaml__logging__level__root": "INFO",
"yaml__logging__level__lavalink": "INFO",
}
DEFAULT_LAVALINK_SETTINGS = {
"host": DEFAULT_LAVALINK_YAML["yaml__server__address"],
"rest_port": DEFAULT_LAVALINK_YAML["yaml__server__port"],
"ws_port": DEFAULT_LAVALINK_YAML["yaml__server__port"],
"password": DEFAULT_LAVALINK_YAML["yaml__lavalink__server__password"],
"secured_ws": False,
"java__Xms": MIN_JAVA_RAM,
"java__Xmx": MAX_JAVA_RAM,
}
def sizeof_fmt(num: Union[float, int]) -> str:
for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]:
if abs(num) < 1024.0:
return f"{num:3.1f}{unit}"
num /= 1024.0
return f"{num:.1f}Y"
# This assumes all keys with `_` should be converted from `part1_part2` to `part1-part2`
def convert_function(key: str) -> str:
return key.replace("_", "-")
def change_dict_naming_convention(data) -> dict:
new = {}
for k, v in data.items():
new_v = v
if isinstance(v, dict):
new_v = change_dict_naming_convention(v)
elif isinstance(v, list):
new_v = list()
for x in v:
new_v.append(change_dict_naming_convention(x))
new[convert_function(k)] = new_v
return new
class CacheLevel:
__slots__ = ("value",)
@@ -216,33 +323,28 @@ class PlaylistScope(Enum):
return list(map(lambda c: c.value, PlaylistScope))
def task_callback_exception(task: asyncio.Task) -> None:
with contextlib.suppress(asyncio.CancelledError, asyncio.InvalidStateError):
if exc := task.exception():
log.exception("%s raised an Exception", task.get_name(), exc_info=exc)
def task_callback_debug(task: asyncio.Task) -> None:
with contextlib.suppress(asyncio.CancelledError, asyncio.InvalidStateError):
if exc := task.exception():
log.debug("%s raised an Exception", task.get_name(), exc_info=exc)
def task_callback_verbose(task: asyncio.Task) -> None:
with contextlib.suppress(asyncio.CancelledError, asyncio.InvalidStateError):
if exc := task.exception():
log.verbose("%s raised an Exception", task.get_name(), exc_info=exc)
def task_callback_trace(task: asyncio.Task) -> None:
with contextlib.suppress(asyncio.CancelledError, asyncio.InvalidStateError):
if exc := task.exception():
log.trace("%s raised an Exception", task.get_name(), exc_info=exc)
def has_internal_server():
def has_managed_server():
async def pred(ctx: commands.Context):
if ctx.cog is None:
return True
external = await ctx.cog.config.use_external_lavalink()
return not external
return commands.check(pred)
def has_unmanaged_server():
async def pred(ctx: commands.Context):
if ctx.cog is None:
return True
external = await ctx.cog.config.use_external_lavalink()
return external
return commands.check(pred)
async def replace_p_with_prefix(bot: Red, message: str) -> str:
"""Replaces [p] with the bot prefix"""
prefixes = await bot.get_valid_prefixes()
prefix = re.sub(rf"<@!?{bot.user.id}>", f"@{bot.user.name}".replace("\\", r"\\"), prefixes[0])
return message.replace("[p]", prefix)