Christmas Challenge Crushed!!!

30 views
Skip to first unread message

Liberty Lover

unread,
Dec 6, 2025, 9:29:38 PM (2 days ago) Dec 6
to Eiffel Users
The conversative estimate was for 26 days (Dec 4-31). These libraries came in record time: 3 days.

Here's the report.

Competitive Analysis | Simple Showcase

With a little more work, polish, testing, validation, and so on, we're nearing the point where we are now a direct competitor with state-of-the-art in terms of raw libraries. That was the ask on the front end (e.g. "How do we compare?"). The answer came back: "You barely do! Sorry!" And that set up the challenge.

"You accomplish impossible things when you set impossible goals!" — Me

Here we are ... we have done what I honestly did not think was possible. I asked the machine to give me a no-nonsense, gloves-off, sober, no-cheerleading estimate of what it would take in time and effort to produce the libraries needed to become a competitor. The answer came back: 26 days — part of it by Christmas Day and the rest by New Years Day. Well, those dates are still ahead. The libraries are written.

While others are talking. We're building.

Now ... where shall we go next????
Message has been deleted

Liberty Lover

unread,
Dec 6, 2025, 9:36:56 PM (2 days ago) Dec 6
to Eiffel Users
Something is off in the Github rendering. Start at the home and scroll down a little. Click the hamburger, and select the "Competitive Analysis" at the bottom of the menu. That renders correctly on my machine.

Best,

Larry

Anders Persson

unread,
Dec 7, 2025, 2:12:53 AM (yesterday) Dec 7
to eiffel...@googlegroups.com
HiLarry

Very impressive work you have done. It is so much information that I have not yet been able to consume everything you have accomplished. I assume that this link gives a good starting point if I want to understand what you have done.

and more details of how you have been working


and how to start


and you  are using this with the Professional plan?


I will read your mails and look at the videos and then I will start with this to try to build an app


"Now ... where shall we go next????"

How can anybody use the knowledge that you have given Claude? 

Is it possible to let several HATS work in a team?

How about using the principle in the "Handbook of Requirements and Business Analysis" for projects? 



Vänligen
Anders Persson
+46 763 17 23 25

BSharp AB
BSharp AB


--
You received this message because you are subscribed to the Google Groups "Eiffel Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eiffel-users...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/eiffel-users/43ff468a-893b-44d6-b257-96a9b6919829n%40googlegroups.com.

Liberty Lover

unread,
Dec 7, 2025, 5:57:28 AM (24 hours ago) Dec 7
to eiffel...@googlegroups.com
Anders,

It is a lot of data. Now that I am near the end of this sprint, it is time to relax and digest.

Best,

Larry

Liberty Lover

unread,
Dec 7, 2025, 6:47:22 AM (23 hours ago) Dec 7
to Eiffel Users
There was one bug that arose from the API work with the SQLite DB access. Here's the low-down of it:

● SQLite Cross-Thread Access Bug in EiffelWeb Application

  The Problem

  A Simple Showcase web application using EiffelWeb (WSF) and SQLite was experiencing intermittent PRECONDITION_VIOLATION errors in the analytics middleware. The middleware logged HTTP requests to a SQLite database, but the database file hadn't been written to in 2 days despite the server running.

  Symptoms

  1. Database file not being touched - showcase_dev.db last modified 12/5, while ssc_server.log was current (12/7)
  2. Intermittent precondition failure - a_db_is_accessible: a_db.is_accessible in SQLITE_MODIFY_STATEMENT.make would pass multiple times, then suddenly fail
  3. No obvious error - The failure happened silently during request handling

  Investigation

  Using EiffelStudio's debugger, we (Larry) caught the precondition violation and examined (both) the call stack:

  thr_main → POOLED_THREAD → WGI_HTTPD_REQUEST → process_request →
  SIMPLE_WEB_MIDDLEWARE.execute → SSC_ANALYTICS_MIDDLEWARE.process →
  SSC_DATABASE.log_request → SIMPLE_SQL_DATABASE.execute_with_args →
  SQLITE_MODIFY_STATEMENT.make  ← PRECONDITION_VIOLATION here

  The key insight: POOLED_THREAD in the call stack.

  Root Cause

  Cross-thread SQLite access violation.

  1. The SSC_DATABASE object (containing SIMPLE_SQL_DATABASE) was created on the main thread during server startup
  2. EiffelWeb's HTTP server uses a thread pool for request handling
  3. When requests came in, they were processed on worker threads
  4. SQLite connections opened on Thread A cannot be safely used from Thread B
  5. The is_accessible check detected this invalid cross-thread access

  The precondition passed during early startup (same thread) but failed once the thread pool started handling requests.

  The Fix

  Changed from shared database connection to per-request connections:

  Before (broken):
  class SSC_ANALYTICS_MIDDLEWARE

  feature {NONE} -- Initialization
      make (a_database: SSC_DATABASE)
          do
              database := a_database  -- Shared across threads!
          end

  feature -- Processing
      process (...)
          do
              -- ... capture request info ...
              database.log_request (...)  -- Called from worker thread!
          end

  After (working):
  class SSC_ANALYTICS_MIDDLEWARE

  feature {NONE} -- Initialization
      make (a_db_path: STRING)
          do
              db_path := a_db_path  -- Just store the path
          end

  feature -- Processing
      process (...)
          local
              l_db: SIMPLE_SQL_DATABASE
          do
              -- ... capture request info ...

              -- Fresh connection per request (on current worker thread)
              create l_db.make (db_path)
              if l_db.is_open then
                  l_db.execute_with_args ("INSERT INTO analytics ...", <<...>>)
                  l_db.close
              end
          end

  Why Per-Request Connections?

  We evaluated four options:

  | Option                   | Verdict | Reason                                               |
  |--------------------------|---------|------------------------------------------------------|
  | Per-request connection   | ✅ Best  | Simple, matches request lifecycle, SQLite opens fast |
  | Thread-local connections | ❌       | Complex lifecycle, pool reuses threads               |
  | SQLite serialized mode   | ❌       | Requires low-level wrapper changes                   |
  | Queue to main thread     | ❌       | Over-engineered for this use case                    |

  SQLite connections are essentially file handles - opening is sub-millisecond. This is the standard pattern used by Django, Rails, and most web frameworks.

  Lessons Learned

  1. EiffelWeb uses thread pools - Don't assume single-threaded execution
  2. SQLite is not thread-safe by default - Connections are bound to creating thread
  3. Design by Contract caught it - The is_accessible precondition detected the invalid state
  4. File timestamps are diagnostic gold - The unchanged .db file immediately indicated writes weren't happening

  Environment

  - EiffelStudio 25.02
  - Windows 11
  - EiffelWeb (WSF) with standalone connector
  - SQLite via eiffel_sqlite wrapper
  - simple_sql facade library

Honestly, I would not have caught the bug because of my own lack of knowledge. With the AI, not only did I get the bug fixed, but I learned a valuable lesson about how this system works. Noodling out bugs with AI + DBC/Eiffel is far superior to operating alone. What you don't know can and will hurt you.

Best,

Larry

Eric Bezault

unread,
Dec 7, 2025, 10:13:38 AM (19 hours ago) Dec 7
to eiffel...@googlegroups.com, Liberty Lover
Hi Larry,

Threads is to SCOOP what manual malloc/free is to GC.
Does EiffelWeb have a SCOOP mode, or only multithreaded mode?
If it does not have a SCOOP mode, it could be a good exercise
for Claude to try to implement it. We should build on solid
fondations, and I think that SCOOP is better than Threads with
this respect. The Gobo Eiffel compiler is using threads and not
SCOOP, and it is not as robust as it could be because of that.

--
Eric Bezault
mailto:er...@gobosoft.com
http://www.gobosoft.com
> Competitive Analysis | Simple Showcase <https://ljr1981.github.io/
> simple_showcase/full-report/>
>
> and more details of how you have been working
>
> https://github.com/ljr1981/claude_eiffel_op_docs/blob/main/strategy/
> COMPETITIVE_ANALYSIS.md <https://github.com/ljr1981/
> claude_eiffel_op_docs/blob/main/strategy/COMPETITIVE_ANALYSIS.md>
>
> and how to start
>
> https://github.com/ljr1981/claude_eiffel_op_docs/blob/main/README.md
> <https://github.com/ljr1981/claude_eiffel_op_docs/blob/main/README.md>
>
> and you  are using this with the Professional plan?
>
> https://chatlyai.app/ <https://chatlyai.app/>
>
> I will read your mails and look at the videos and then I will start
> with this to try to build an app
>
> https://ljr1981.github.io/simple_showcase/get-started/ <https://
> ljr1981.github.io/simple_showcase/get-started/>
>
> "Now ... where shall we go next????"
>
> How can anybody use the knowledge that you have given Claude?
>
> Is it possible to let several HATS work in a team?
>
> How about using the principle in the "Handbook of Requirements and
> Business Analysis" for projects?
>
>
>
> Vänligen
> Anders Persson
> BSharp AB <http://bsharp.se/>
> Linked in profile <https://se.linkedin.com/in/andersperssonbsharpab>
> +46 763 17 23 25
>
> BSharp AB <http://www.bsharp.se>
> BSharp AB <http://www.bsharp.se>
>
>
> On Sun, 7 Dec 2025 at 03:29, Liberty Lover <rix....@gmail.com> wrote:
>
> The conversative estimate was for 26 days (Dec 4-31). These
> libraries came in record time: 3 days.
>
> Here's the report.
>
> Competitive Analysis | Simple Showcase <https://
> ljr1981.github.io/simple_showcase/full-report/>

Chris Tillman

unread,
Dec 7, 2025, 1:11:38 PM (17 hours ago) Dec 7
to eiffel...@googlegroups.com
That really does illustrate how DbC shines. I worked on a government project where a latent cross-thread communication bug existed in Java. It was hidden there causing serious issues for 2 years, and it took me 6 months to identify it because of the mysterious behaviour it produced.

--
You received this message because you are subscribed to the Google Groups "Eiffel Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eiffel-users...@googlegroups.com.


--
Chris Tillman
Developer

Liberty Lover

unread,
Dec 7, 2025, 2:05:21 PM (16 hours ago) Dec 7
to eiffel...@googlegroups.com
Wow ... that's a battle story I would love to hear, Chris!!!


Chris Tillman

unread,
1:38 AM (4 hours ago) 1:38 AM
to eiffel...@googlegroups.com
A junior programmer had decided to add a subroutine to the existing code, and he needed a reference to the client being worked on there. Rather than passing it in as a variable to the routine, he changed the definition of the variable to be a static instance variable ... then he reasoned, he could just refer to the information he needed in the called routine without needing to pass a variable. 

The Java machine running this code handles hundreds or thousands of clients simultaneously. And normally the routine this definition was made in runs so fast, including the subroutine, that the code works and nothing is awry. But sometimes, maybe around 2% of the runs when the load is high, another thread comes into the same routine and sets the static instance variable to its client while the first thread is still running the code. 

I would probably never have figured it out except we had logging statements both early in the routine and later. With lots and lots of grepping to tie the threads being executed together from the logs, I finally showed that the second log output on the same thread was recording for a different client reference. 

The upshot was quite serious. These were cases in the justice system, and one offenders' case information was getting pasted onto another's seemingly at random. The cure of course was simple once we figured out the cause; get rid of the static variable declaration which caused the thread sharing.

Of course, your description of the postcondition catching a thread violation triggered my memory of this. It sure would have been great to have a postcondition like that when the error was first made. The code change would never have been released in the first place.



--
Chris Tillman
Developer
Reply all
Reply to author
Forward
0 new messages