Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,565
|
Comments: 51,184
Privacy Policy · Terms
filter by tags archive
time to read 2 min | 384 words

The very first draft of Impleo (my CMS system), was based on sound design principles. It had good separation between the different parts (it actually had 4 or 5 projects). At some point I took a look at the code and couldn’t find it. There was a lot of infrastructure, but nothing that I could actually point to and say: “This is the application logic”.

I decided to take a different approach, created a new WebForms project, and started everything from scratch. I ported some of the code from the original solution, but mostly we just built new stuff. I stubbornly decided that I am going to apply YAGNI here, so I just scrapped everything that I usually do and started a typical web forms project, no IoC, no testing, nothing.

As expected, initially we had a really nice velocity, and if I had to hold my nose a bit during some parts, I was willing to go with that.

The next stage with Impleo, however, is to turn it from just a content management system into a website framework. The difference between the two are significant, while a CMS is just about content, a website framework allows you to add custom pages and application behavior. There is an added difficulty in that I want to use Impleo for multiple sites, doing different things.

That turn it from just a custom application to a platform, and the roles there are quite different. For that, just going with the approach that I used so far would have been disastrous. I tried, and spiked some things, but none of them made me  happy. I decided that I really need to stop, and since I have a working version, I can “refactor” it to a better shape. I put refactor in double quotes intentionally.

My method included creating a new MVC project, add some integration tests and then porting everything from the WebForms to the MVC project. Overall, it was a pretty simple, if tedious, process.

The most difficult thing along the way was that I was doing this while I was flying, and for some stupid reason, I could either charge the laptop battery or use the laptop, so I had to make frequent stops to recharge.

time to read 1 min | 148 words

Occasionally I need to do development stuff things that are potentially destructive.

The ResetDatabase action will blow away the database, which I need to do for tests and when I am making big changes. But what I absolutely does not want is to have in production.

image

My method is to require three different things to be true to enable this:

  • You must issue a local request (so you are physically on the machine where the system is sitting).
  • You are logged on as a user and as an administrator (that is the superAdmin part).
  • You are running on a debug build.

Hopefully, I won’t blow the production database.

time to read 3 min | 455 words

That really depends on the type of application that you write and what kind of operations team it is going to have.

I have applications that I setup, then forget about (this blog being one of them). In those types of applications, having a log in production is a burden, I need to purge it occasionally, or write the code to purge it automatically.

Then I have applications that have a strong operations team, where people are looking at the application every single day. An alert raised from the system is actually going to be looked at by a human before irate customers start calling. In those cases, a lot is pretty important, and understanding how to properly distinguish between real errors (human needs to look at) and transient ones (do a review once a month) is pretty important.

Setting things up is that I have production sites log only error conditions, which is pretty common, is also a mistake, as a simple example, I had once seen a log that where 40% of the errors where users coming back to the site after the session has timed out, and the error was leading them to the error page.

The way I try to do things is:

  • Pay attention to messages that arrive to the error queue, see if there is anything that can be done about them.
  • Log & alert any time that an error crosses the system boundary (if the users see an error page, I really want to know about it).
  • Setup things so I can change log levels in productions without restarting / redeployment, etc.

Please note that I am making a distinction here between developer’s log and audit trails or operations information. Depending on the type of system that you have, and the requirements on it, those two can be a gold mine when trying to troubleshoot issues.

Providing things like performance counters or access to internal state in your application is also important. For example, being able to ask the app for the worst performing queries is a great way of troubleshooting perf issues. Or querying the cache miss ratios, etc. It isn’t just logging that gives you visibility into the system.

Something that I haven’t had the chance to do yet (but that I would like to try) is to plug the NH Prof backend (which is basically an event aggregation and analysis system) as a way to analyze log streams. That way, even if you do have some logging turned on, it doesn’t stay in its raw form, but is translated to something much more concise and understandable.

time to read 4 min | 737 words

I usually post things of moderate difficulty, let us see if you can not only figure this one out, but where that bug exists.

Given the following class & mapping:

public class User
{
    public virtual string Username { get; set; }
    public virtual ICollection<string> AllowedPaths { get; set; }

    public User()
    {
        AllowedPaths = new HashSet<string>();
    }
}

<
class name="User" table="Users"> <id name="Username"> <generator class="assigned"/> </id> <set name="AllowedPaths" table="UsersAllowPaths"> <key column="`User`" not-null="true"/> <element column="Path" type="System.String" not-null="true"/> </set> </class>

I have the following code:

public class Program
{
    public static void Main()
    {
        Configuration configuration = new Configuration().Configure("nhibernate.config");
        ISessionFactory sessionFactory = configuration.BuildSessionFactory();
        new SchemaExport(configuration).Create(true, true);


        using (ISession s = sessionFactory.OpenSession())
        using (ITransaction tx = s.BeginTransaction())
        {
            s.Save(new User
            {
                Username = "ayende",
                AllowedPaths = {"/users", "/meetings"}
            });

            tx.Commit();
        }

        using (ISession s = sessionFactory.OpenSession())
        using (ITransaction tx = s.BeginTransaction())
        {
            var user = s.Get<User>("Ayende");
            Console.WriteLine("Found user {0}", user.Username);
            Console.WriteLine("Allowed paths:");
            foreach (string allowedPath in user.AllowedPaths)
            {
                Console.WriteLine("\t{0}", allowedPath);
            }

            tx.Commit();
        }
    }
}

First, and without running the code!

  • What is the expected output?
  • Am I doing something wrong here?

Then, run the code, and answer them again.

You can download the project here: http://github.com/ayende/NHibernate-Challanges, sub folder TrickyBug

time to read 1 min | 190 words

We have mostly done all the infrastructure work that actually needed to be done, what is left is polishing and “i18n” (for lack of a better word).

One of the things that I want to do with L2SPRof  is to create a different identity from NHProf and HProf.

This is me just playing around, not something that is final, but I would still like your thoughts:

image

Two closing notes:

  • It took me about 30 minutes of playing with Blend to get this to work. As usual, Christopher and Rob are flat out amazing, not just for creating good UI (and great UI architecture), but doing it in such a way that a self processed UI n00b can create reasonable results from it.
  • I know that there are some people that don’t like the divergence from the standard Windows scheme. I am already familiar with the arguments, and I have good reasons to go that route.

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. Production Postmortem (52):
    07 Apr 2025 - The race condition in the interlock
  2. RavenDB (13):
    02 Apr 2025 - .NET Aspire integration
  3. RavenDB 7.1 (6):
    18 Mar 2025 - One IO Ring to rule them all
  4. RavenDB 7.0 Released (4):
    07 Mar 2025 - Moving to NLog
  5. Challenge (77):
    03 Feb 2025 - Giving file system developer ulcer
View all series

RECENT COMMENTS

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}