diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/PrefixedDefaultThreadFactory.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/PrefixedDefaultThreadFactory.java new file mode 100644 index 00000000..7c107e4f --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/utils/PrefixedDefaultThreadFactory.java @@ -0,0 +1,99 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2024. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.utils; + + +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + + +/******************************************************************************* + ** ThreadFactory implementation that puts a common prefix on all threads. + ** + ** Makes it so that, instead of having 100s of pool-x-thread-y names that are + ** hard to tell apart, they can have a prefix: MyService-pool-x-thread-y, vs + ** YourThing-pool-x-thread-y. + ** + ** You can put '-' at the end of your threadNamePrefix (constructor arg) or + ** you can omit it, either way, we'll make it look like shown above. + *******************************************************************************/ +public class PrefixedDefaultThreadFactory implements ThreadFactory +{ + private final String threadNamePrefix; + private final ThreadFactory threadFactory; + + + + /******************************************************************************* + ** Constructor + ** + *******************************************************************************/ + public PrefixedDefaultThreadFactory(String threadNamePrefix) + { + if(StringUtils.hasContent(threadNamePrefix)) + { + this.threadNamePrefix = threadNamePrefix.replaceAll("-+$", "") + "-"; + } + else + { + this.threadNamePrefix = ""; + } + + threadFactory = Executors.defaultThreadFactory(); + } + + + + /******************************************************************************* + ** Constructor + ** + *******************************************************************************/ + public PrefixedDefaultThreadFactory(Class callerClass) + { + this(callerClass != null ? callerClass.getSimpleName() : ""); + } + + + + /******************************************************************************* + ** Constructor + ** + *******************************************************************************/ + public PrefixedDefaultThreadFactory(Object caller) + { + this(caller != null ? caller.getClass() : null); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public Thread newThread(Runnable r) + { + Thread thread = threadFactory.newThread(r); + thread.setName(threadNamePrefix + thread.getName()); + return (thread); + } + +} diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/PrefixedDefaultThreadFactoryTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/PrefixedDefaultThreadFactoryTest.java new file mode 100644 index 00000000..8c0394d2 --- /dev/null +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/PrefixedDefaultThreadFactoryTest.java @@ -0,0 +1,65 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2024. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.utils; + + +import com.kingsrook.qqq.backend.core.BaseTest; +import com.kingsrook.qqq.backend.core.actions.tables.InsertAction; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + + +/******************************************************************************* + ** Unit test for PrefixedDefaultThreadFactory + *******************************************************************************/ +class PrefixedDefaultThreadFactoryTest extends BaseTest +{ + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void test() + { + assertThat(new PrefixedDefaultThreadFactory("ItsMe").newThread(this::noop).getName()).startsWith("ItsMe-pool"); + assertThat(new PrefixedDefaultThreadFactory("ItsMe-").newThread(this::noop).getName()).startsWith("ItsMe-pool"); + assertThat(new PrefixedDefaultThreadFactory("ItsMe--").newThread(this::noop).getName()).startsWith("ItsMe-pool"); + assertThat(new PrefixedDefaultThreadFactory((String) null).newThread(this::noop).getName()).startsWith("pool"); + assertThat(new PrefixedDefaultThreadFactory((Class) null).newThread(this::noop).getName()).startsWith("pool"); + assertThat(new PrefixedDefaultThreadFactory((Object) null).newThread(this::noop).getName()).startsWith("pool"); + assertThat(new PrefixedDefaultThreadFactory("").newThread(this::noop).getName()).startsWith("pool"); + assertThat(new PrefixedDefaultThreadFactory(" ").newThread(this::noop).getName()).startsWith("pool"); + assertThat(new PrefixedDefaultThreadFactory(this).newThread(this::noop).getName()).startsWith(getClass().getSimpleName() + "-pool"); + assertThat(new PrefixedDefaultThreadFactory(InsertAction.class).newThread(this::noop).getName()).startsWith(InsertAction.class.getSimpleName() + "-pool"); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + void noop() + { + System.out.println("noop"); + } + +} \ No newline at end of file