How to customize NettyApplicationEngine in a koin-ktor project? - koin

Hi the vanilla ktor Netty config does not allow long URLs, you need to customize the HttpServerCodec buffer sizes. How do you get access to this in a koin-ktor application?

I figured out a crappy way. I changed to use own main which was basically a fork of Netty.EngineMain.
// Copy and paste of the io.ktor.server.netty.EngineMain
fun main(args: Array<String>) {
val applicationEnvironment = commandLineEnvironment(args)
NettyApplicationEngine(applicationEnvironment, { loadConfiguration(applicationEnvironment.config) }).start()
}
// Copy and paste of the io.ktor.server.netty.EngineMain
private fun NettyApplicationEngine.Configuration.loadConfiguration(config: ApplicationConfig) {
val deploymentConfig = config.config("ktor.deployment")
loadCommonConfiguration(deploymentConfig)
deploymentConfig.propertyOrNull("requestQueueLimit")?.getString()?.toInt()?.let {
requestQueueLimit = it
}
deploymentConfig.propertyOrNull("shareWorkGroup")?.getString()?.toBoolean()?.let {
shareWorkGroup = it
}
deploymentConfig.propertyOrNull("responseWriteTimeoutSeconds")?.getString()?.toInt()?.let {
responseWriteTimeoutSeconds = it
}
// Allow long URLs to be accepted
httpServerCodec = {
HttpServerCodec(1048576, 1048576, 1048576)
}
}

Related

Extract day/night resources from Theme.MaterialComponents.DayNight.DarkActionBar

I'm using Theme.MaterialComponents.DayNight.DarkActionBar as my app's theme and would like to programmatically get, for example, the android.R.attr.textColorPrimary color for both dark mode and light mode. Is this possible? If so, how?
#ColorInt
fun getStyledDayNightColor(context: Context, #AttrRes attrResId: Int, night: Boolean): Int {
val configuration = Configuration(context.resources.configuration).apply {
uiMode = if (night) {
Configuration.UI_MODE_NIGHT_YES
} else {
Configuration.UI_MODE_NIGHT_NO
}
}
val contextWrapper = ContextThemeWrapper(context, R.style.Theme_MaterialComponents_DayNight).apply {
applyOverrideConfiguration(configuration)
}
val ta = contextWrapper.obtainStyledAttributes(intArrayOf(attrResId))
return ta.getColor(0, Color.GREEN).also {
ta.recycle()
}
}

Kotlin how to combine different receivers via with clause without repeating it

I have Parent-Search-Child system as below:
class Room
class Building {
fun find(by: By) = Room()
}
sealed class By {
abstract fun search(): Room
class ById(id: String) : By() {
override fun search(): Room = Room() // epic search method
}
class ByName(name: String) : By() {
override fun search(): Room = Room() // epic search method
}
class Byurpose(purpose: String) : By() {
override fun search(): Room = Room() // epic search method
}
companion object {
fun id(id: String) = ById(id)
fun name(name: String) = ByName(name)
fun purpose(purpose: String) = Byurpose(purpose)
}
}
Which can be used as follows:
val building = Building()
val room = building.find(By.name("Toilet"))
However, I am not very satisfied with the current syntax, which could be much less verbose in Kotlin. In addition, building.find can appear thousands times in the code. I could implement it differently, but actually I don't own Room, Building or By classes, so I can't. Thus this was my approach:
I implemented context class that stores Building reference, and use it internally as source for search methods:
class BuildingContext(private val building: Building) {
fun String.findById() = building.find(By.id(this))
fun String.findByName() = building.find(By.name(this))
fun String.findByPurpose() = building.find(By.purpose(this))
}
It can be used as below:
with(BuildingContext(building)) {
val room2 = "Toilet".findByName()
}
After that I noticed that I only use one search method in 99% cases, so (for sake of even shorter syntax!) I implemented following classes:
object AlwaysSearchById {
fun String.find(building: Building) = building.find(By.id(this))
}
object AlwaysSearchByName {
fun String.find(building: Building) = building.find(By.name(this))
}
object AlwaysSearchByPurpose {
fun String.find(building: Building) = building.find(By.purpose(this))
}
Which can be used this way:
with(AlwaysSearchByName) {
val room3 = "Toilet".find(building)
}
Unfortunately, building reference appears again. The ideal syntax would be "Toilet".find(). I could fix it re-implementing Always~ classes as follows:
class AlwaysSearchByNameV2(private val building: Building) {
fun String.find() = building.find(By.name(this))
}
And it would be used as below:
with(AlwaysSearchByNameV2(building)) {
val room = "Toilet".find()
}
But it some cases, I would like to access BuildingContext methods as well, so So I have to write:
with(BuildingContext(building)) {
with(AlwaysSearchByNameV2(building)) {
val toilet = "Toilet".find()
val randomRoom = "123".findById()
}
}
The question is - How I reduce multiple with clauses in this case?
In the example above there are only 2 with clauses, but it's only basic example. In real world there could be dozens of them, and writing with(with(with(with(with... would surely be a pain.
On the side note this doesn't work:
with(BuildingContext(building), AlwaysSearchByNameV2(building)) {
val toilet = "Toilet".find()
val randomRoom = "123".findById()
}
nor this
with(*arrayOf(BuildingContext(building), BuildingContext(building))) {
val toilet = "Toilet".find()
val randomRoom = "123".findById()
}
You can write custom scoping functions instead of relying on with all the time. For example you can add an extension function that will run a block of code in scope of AlwaysSearchByNameV2 object:
inline fun BuildingContext.byName(f : AlwaysSearchByNameV2.() -> Unit) = AlwaysSearchByNameV2(building).apply(f)
And use it:
with(BuildingContext(building)) { // this: BuildingContext
byName { // this: AlwaysSearchByNameV2
val toilet = "Toilet".find()
val randomRoom = "123".findById() // can still refer to BuildingContext
}
// back to this: BuildingContext
}

DataTable to Generic List Using Task to Make it faster

Have started to Make the conversion faster from dataTable to List as I have 20K record in datatable and converting it in normal way takes 5 to 7 Minutes. SO I thought to Make it faster by using Parallel.ForEach or Task but still no benefit - Any suggestion please. Mu code is as below :
public static List<T> FillFromStoredProc<T>(string storedproc, SqlParameter[] prms) where T : IReadOnlyDatabaseObject, new()
{
DataTable dt = DatabaseHelper.runStoredProc(Configuration.Instance.ConnectionString, storedproc, prms);
ConcurrentBag<T> bag = new ConcurrentBag<T>();
IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
Parallel.ForEach(dt.AsEnumerable(), new ParallelOptions { MaxDegreeOfParallelism = 10 }, Drow => {
bag.Add(GetFromDataRow<T>(Drow, properties));
});
return bag.ToList();
}
public static T GetFromDataRow<T>(DataRow dr, IList<PropertyInfo> properties) where T : IReadOnlyDatabaseObject, new()
{
T ret = new T();
ret.LoadFromDataRowAsync(dr, properties);
return ret;
}
public virtual void LoadFromDataRowAsync(DataRow dr, IList<PropertyInfo> properties)
{
Parallel.ForEach(properties, new ParallelOptions { MaxDegreeOfParallelism = 10 }, prop =>
{
try
{
if (dr.Table.Columns.Contains(prop.Name))
{
if (prop.PropertyType.BaseType.Name == "Enum")
{
prop.SetValue(this, Enum.Parse(prop.PropertyType, dr[prop.Name].ToString()));
}
else
{
var val = DatabaseHelper.ConvertFromDBVal(prop.GetType(), dr[prop.Name]);
if (prop.PropertyType == typeof(DateTime))
{
// Convert back from DB value
if ((DateTime)(val) == SqlDateTime.MinValue)
{
val = DateTime.MinValue;
}
}
prop.SetValue(this, val);
}
}
}
catch
{
}
});
}
Please help me to make this faster. Thanks
Nesting parallelism is useless and must be avoided, because usually it only makes the overall performance worse.
Your bottleneck is the reflection - it is slow. You should come up with an alternative. For example, you can create a base class for your generic types, and use a virtual method that maps the name of a property to an actual property. It sounds like quite some grinding and dirty work, but it will be more efficient.

How to use MockK to mock an observable

I have a data provider that has an Observable<Int> as part of the public API. My class under test maps this into a Observable<String>.
How do I create a mock so that it can send out different values on the data provider's observable?
I can do it using a Fake object, but that is a lot of work that I don't think is necessary with MockK.
Simplified code:
interface DataProvider {
val numberData:Observable<Int>
}
class FakeDataProvider():DataProvider {
private val _numberData = BehaviorSubject.createDefault(0)
override val numberData = _numberData.hide()
// Note: the internals of this class cause the _numberData changes.
// I can use this method to fake the changes for this fake object,
// but the real class doesn't have this method.
fun fakeNewNumber( newNumber:Int ) {
_numberData.onNext( newNumber )
}
}
interface ClassUnderTest {
val stringData:Observable<String>
}
class MyClassUnderTest( dataProvider: DataProvider ):ClassUnderTest {
override val stringData = dataProvider.numberData.map { "string = " + it.toString() }
}
class MockKTests {
#Test fun testUsingFakeDataProvider() {
val fakeDataProvider = FakeDataProvider()
val classUnderTest = MyClassUnderTest( fakeDataProvider )
val stringDataTestObserver = TestObserver<String>()
classUnderTest.stringData.subscribe( stringDataTestObserver )
fakeDataProvider.fakeNewNumber( 1 )
fakeDataProvider.fakeNewNumber( 2 )
fakeDataProvider.fakeNewNumber( 3 )
// Note we are expecting the initial value of 0 to also come through
stringDataTestObserver.assertValuesOnly( "string = 0", "string = 1","string = 2","string = 3" )
}
// How do you write the mock to trigger the dataProvider observable?
#Test fun testUsingMockDataProvider() {
val mockDataProvider = mockk<DataProvider>()
// every { ... what goes here ... } just Runs
val classUnderTest = MyClassUnderTest( mockDataProvider )
val stringDataTestObserver = TestObserver<String>()
classUnderTest.stringData.subscribe( stringDataTestObserver )
// Note we are expecting the initial value of 0 to also come through
stringDataTestObserver.assertValuesOnly( "string = 0", "string = 1","string = 2","string = 3" )
}
}
Try to use following:
every { mockDataProvider.numberData } answers { Observable.range(1, 3) }
And maybe you need to use another way to make a mock object, like this:
val mockDataProvider = spyk(DataProvider())
Do something like this where we create an observable fakelist of the observable
var fakeList :List<Quiz> = (listOf<Quiz>(
Quiz("G1","fromtest","","",1)
))
var observableFakelist = Observable.fromArray(fakeList)
you can then return your observableFakelist.

Bridge channel to a sequence

This code is based on Coroutines guide example: Fan-out
val inputProducer = produce<String>(CommonPool) {
(0..inputArray.size).forEach {
send(inputArray[it])
}
}
val resultChannel = Channel<Result>(10)
repeat(threadCount) {
launch(CommonPool) {
inputProducer.consumeEach {
resultChannel.send(getResultFromData(it))
}
}
}
What is the right way to create a Sequence<Result> that will provide results?
You can get the channel .iterator() from the ReceiveChannel and then wrap that channel iterator into a Sequence<T>, implementing its normal Iterator<T> that blocks waiting for the result on each request:
fun <T> ReceiveChannel<T>.asSequence(context: CoroutineContext) =
Sequence {
val iterator = iterator()
object : AbstractIterator<T>() {
override fun computeNext() = runBlocking(context) {
if (!iterator.hasNext())
done() else
setNext(iterator.next())
}
}
}
val resultSequence = resultChannel.asSequence(CommonPool)
I had the same problem, and in the end I came up with this rather unusual/convoluted solution:
fun Channel<T>.asSequence() : Sequence<T> {
val itr = this.iterator()
return sequence<Int> {
while ( runBlocking {itr.hasNext()} ) yield( runBlocking<T> { itr.next() } )
}
}
I do not think it is particular efficient (go with the one provided by #hotkey), but it has a certain appeal to me at least.

Resources