|
1 | 1 | package dev.openfeature.sdk; |
2 | 2 |
|
| 3 | +import com.vmlens.api.AllInterleavings; |
3 | 4 | import dev.openfeature.sdk.exceptions.ExceptionUtils; |
4 | 5 | import dev.openfeature.sdk.exceptions.FatalError; |
5 | 6 | import dev.openfeature.sdk.exceptions.GeneralError; |
|
8 | 9 | import dev.openfeature.sdk.internal.AutoCloseableLock; |
9 | 10 | import dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock; |
10 | 11 | import dev.openfeature.sdk.internal.ObjectUtils; |
| 12 | +import dev.openfeature.sdk.providers.memory.Flag; |
| 13 | +import dev.openfeature.sdk.providers.memory.InMemoryProvider; |
11 | 14 | import java.util.ArrayList; |
12 | 15 | import java.util.Arrays; |
13 | 16 | import java.util.Collections; |
14 | 17 | import java.util.HashMap; |
15 | 18 | import java.util.List; |
16 | 19 | import java.util.Map; |
17 | 20 | import java.util.Objects; |
| 21 | +import java.util.concurrent.atomic.AtomicInteger; |
18 | 22 | import java.util.function.Consumer; |
19 | 23 | import lombok.Getter; |
20 | 24 | import lombok.extern.slf4j.Slf4j; |
@@ -180,7 +184,7 @@ private <T> FlagEvaluationDetails<T> evaluateFlag( |
180 | 184 | ProviderState state = stateManager.getState(); |
181 | 185 |
|
182 | 186 | mergedHooks = ObjectUtils.merge( |
183 | | - provider.getProviderHooks(), flagOptions.getHooks(), clientHooks, openfeatureApi.getHooks()); |
| 187 | + provider.getProviderHooks(), flagOptions.getHooks(), getHooks(), openfeatureApi.getHooks()); |
184 | 188 |
|
185 | 189 | EvaluationContext mergedCtx = hookSupport.beforeHooks( |
186 | 190 | type, |
@@ -521,4 +525,117 @@ public Client removeHandler(ProviderEvent event, Consumer<EventDetails> handler) |
521 | 525 | openfeatureApi.removeHandler(domain, event, handler); |
522 | 526 | return this; |
523 | 527 | } |
| 528 | + |
| 529 | + static int jaVar = 0; |
| 530 | + |
| 531 | + /** |
| 532 | + * run. |
| 533 | + * |
| 534 | + * @param args the args |
| 535 | + * @throws InterruptedException something |
| 536 | + */ |
| 537 | + public static void main(String[] args) throws InterruptedException { |
| 538 | + |
| 539 | + System.out.println("OpenFeatureClientTest.testUpdate"); |
| 540 | + final OpenFeatureAPI api = new OpenFeatureAPI(); |
| 541 | + |
| 542 | + var flags = new HashMap<String, Flag<?>>(); |
| 543 | + flags.put("a", Flag.builder().variant("a", "def").defaultVariant("a").build()); |
| 544 | + flags.put("b", Flag.builder().variant("a", "as").defaultVariant("a").build()); |
| 545 | + flags.put("c", Flag.builder().variant("a", "dfs").defaultVariant("a").build()); |
| 546 | + flags.put("d", Flag.builder().variant("a", "asddd").defaultVariant("a").build()); |
| 547 | + api.setProviderAndWait(new InMemoryProvider(flags)); |
| 548 | + var i = 0; |
| 549 | + var c = new AtomicInteger(); |
| 550 | + |
| 551 | + System.out.println("before try"); |
| 552 | + try (AllInterleavings allInterleavings = new AllInterleavings("Concurrent evaluations and hook additions")) { |
| 553 | + while (allInterleavings.hasNext()) { |
| 554 | + c.incrementAndGet(); |
| 555 | + jaVar = 0; |
| 556 | + Thread first = new Thread() { |
| 557 | + @Override |
| 558 | + public void run() { |
| 559 | + jaVar++; |
| 560 | + } |
| 561 | + }; |
| 562 | + first.start(); |
| 563 | + jaVar++; |
| 564 | + first.join(); |
| 565 | + if (jaVar != 2) { |
| 566 | + throw new RuntimeException("jaVar=" + jaVar); |
| 567 | + } |
| 568 | + /* |
| 569 | + var client = api.getClient(); |
| 570 | + var firstReady = new Awaitable(); |
| 571 | + var secondReady = new Awaitable(); |
| 572 | + var startThreads = new Awaitable(); |
| 573 | + Thread first = new Thread() { |
| 574 | + @Override |
| 575 | + public void run() { |
| 576 | + firstReady.wakeup(); |
| 577 | + startThreads.await(); |
| 578 | + client.getStringValue("a", "a"); |
| 579 | + } |
| 580 | + }; |
| 581 | + Thread hookAdder = new Thread() { |
| 582 | + @Override |
| 583 | + public void run() { |
| 584 | + secondReady.wakeup(); |
| 585 | + startThreads.await(); |
| 586 | + client.addHooks(new Hook() {}); |
| 587 | + } |
| 588 | + }; |
| 589 | + hookAdder.start(); |
| 590 | + first.start(); |
| 591 | + firstReady.await(); |
| 592 | + secondReady.await(); |
| 593 | + startThreads.wakeup(); |
| 594 | + first.join(); |
| 595 | + hookAdder.join(); |
| 596 | +*/ |
| 597 | + /*System.out.println("has interlereaving"); |
| 598 | + i++; |
| 599 | + //var latch = new CountDownLatch(1); |
| 600 | + var client = api.getClient(); |
| 601 | + var concurrentModException = new AtomicReference<ConcurrentModificationException>(); |
| 602 | + Thread eval = new Thread(() -> { |
| 603 | + System.out.println("eval"); |
| 604 | + try { |
| 605 | + latch.await(); |
| 606 | + } catch (InterruptedException ignored) { |
| 607 | + } |
| 608 | + client.getStringValue("a", "a"); |
| 609 | + client.getStringValue("b", "a"); |
| 610 | + client.getStringValue("c", "a"); |
| 611 | + client.getStringValue("d", "a"); |
| 612 | +
|
| 613 | + }); |
| 614 | + Thread hookAdder = new Thread(() -> { |
| 615 | + System.out.println("hook adder"); |
| 616 | + try { |
| 617 | + latch.await(); |
| 618 | + } catch (InterruptedException ignored) { |
| 619 | + } |
| 620 | + client.addHooks(new Hook() {}); |
| 621 | +
|
| 622 | + }); |
| 623 | + System.out.println("starting..."); |
| 624 | + //eval.start(); |
| 625 | + //hookAdder.start(); |
| 626 | + System.out.println("started"); |
| 627 | + Thread.sleep(200); |
| 628 | + client.getStringValue("d", "a"); |
| 629 | + client.addHooks(new Hook() {}); |
| 630 | + client.getStringValue("d", "a"); |
| 631 | + //latch.countDown(); |
| 632 | + eval.join(); |
| 633 | + hookAdder.join(); |
| 634 | + System.out.println(concurrentModException.get());*/ |
| 635 | + } |
| 636 | + } |
| 637 | + System.out.println("i = " + i); |
| 638 | + System.out.println("jaVar = " + jaVar); |
| 639 | + System.out.println("c.get() = " + c.get()); |
| 640 | + } |
524 | 641 | } |
0 commit comments